C程序设计语言04 - 指针与数组

指针是保存变量地址的变量

0x00 指针与地址

一元运算符&可用于取一个对象的地址,如: p = &c;, 把变量c的地址赋值给变量p,称p为“指向”c的指针。地址运算符&只能应用于内存中的对象,即变量和数组元素,不能作用于表达式、常量或register类型的变量。

一元运算符*是间接寻址或间接引用运算符。作用于指针时,将访问指针所指向的对象。

指针声明: int *p;,该语句表明表达式*ip的结果是int类型。

0x01 指针与函数参数

由于C语言是以传值的方式将参数值传递给被调用函数,所以调用函数不能直接修改主调函数中变量的值。可以使主调程序将指向所要改变的变量的指针传递给调用函数,这样被调函数可以改变主调函数变量的值。

如:

void swap(int *px, int *py) {
    int temp;

    temp = *px;
    *px = *py;
    *py = temp;
}

0x02 指针与数组

通过数组下标所能完成的任意操作都可以通过指针来实现。一般来说用指针编写的程序比用数组下标编写的程序执行速度快。

“指针加1”意味着指针所指向对象的下一个对象。

数组类型的变量或表达式的值是该数组第0个元素的地址。

int *pa, a[10];
pa = &a[0]; 
pa = a;         //等价于pa = &a[0]; 

一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现。数组名和指针之间的不同之处在于指针是一个变量,而数组名不是,指针可以改变,而数组名不行。

当把数组名传递给一个函数时,实际上传递的是该数组的第一个元素的地址。

在函数定义中,形式参数char s[]char *s是等价的。

0x03 地址算术运算

有效的指针运算包括

  1. 相同类型指针之间的赋值运算
  2. 指针同整数之间的加法和减法运算
  3. 指向相同数组中元素的两个指针间的减法或比较运算
  4. 将指针赋值为0或指针与0之间的比较运算

0x04 字符指针与函数

字符串常量是一个字符数组。字符串常量可以通过一个指向其第一个元素的指针访问。如:

char *pmessage;
pmessage = "now is the time";

0x05 指针数组以及指向指针的指针

指针数组声明

char *lineptr[MAXLINES];

*lineptr[0] 等价于 **ilneptr,前者是是一个指针数组,后者是指向指针的指针,但底层是一样的,因为int a[]; a[0] == *a

0x06 多维数组

二维数组是一种特殊的一维数组,它的每个元素也是一个一维数组。

如果将二维数组作为参数传递给函数,在函数的参数声明中必须指明数组的列数。

一般来说,除数组的第一维可以不指定大小外,其余各维都必须明确指定大小。

注意:

// 下面三种声明作用相同
f(int daytab[2][13]) { ... }
f(int daytab[][13]) { ... }
f(int (*daytab)[13])

0x07 指针数组初始化

char *month_name(int n) {
    satic char *name[] = {
        "Illegal month",
        "January", "February", "March",
        "April", "May", "June", 
        "July", "August", "September",
        "October", "November", "December" 
    };
    ...
}

0x08 指针数组与多维数组

int a[10][20];
int *b[10];

a是一个真正的二维数组,它分配了200个int类型长度的存储单元。b定义仅仅分配了10个指针,并且没有初始化。指针数组的一个重要的优点在于,数组的每一行长度可以不同。

0x09 命令行参数

main(int argc, char *argv[])
// argc表示参数数量,argv是参数的指针数组,程序本身是第一个参数

0x10 指向函数的指针

函数本身不是变量,但可以定义指向函数的指针。

// 函数定义
void qsort(void *lineptr[], int left, int right,
        int (*comp)(void *, void *));

// 函数调用
qsort((void**) lineptr, 0, nlines-1, 
    (int (*)(void*, void*))(numeric ? numcmp : strcmp));

strcmp和numcp是函数地址, 函数不需要使用地址运算符&取值,同数组一样。

通用指针类型void *, 任何类型的指针都可以转换为void *类型,并且在将它转换回原来的类型时不会丢失信息。

int (*comp)(void *, void *))声明中表明comp是一个指向函数的指针,*comp代表一个函数。(*comp)(v[i], v[left])是对指针函数的调用,其中圆括号必须。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容