关于指针与数组这对兄弟

指针和数组是 C 语言中比较重要的知识点,尤其是指针和数组结合之后,很多同学就不清楚是怎么一回事了。在这里结合几个例子,介绍一下我所理解的指针和数组,希望对大家有所帮助。

指针

指针在 C 语言中是一种类型,就和其他基本数据类型一样。通常在32位机器上面占四个字节,在64位机器上占八个字节。指针用来保存其他变量的地址,请看下面整型指针与整型变量的对比:

int main()
{
    int a = 4;      //定义整型变量 a
    int b = 10;     //定义整形变量 b
    int *p = &b;    //定义整型指针 p ,保存变量 b 的地址

    //a 变量和 p 变量的值
    printf("a 变量的值为: %d\n", a);
    printf("p 变量的值为: %p\n", p);
    
    //指针变量的特殊操作
    printf("指针所指向变量的值: %d\n", *p);
    *p = 15;
    printf("指针所指向变量的值: %d\n", *p);
    printf("b 变量的值为: %d\n", b);
    return 0;
}

解释:
在上面的程序中,定义了整型变量 a、整型变量 b 和 整型指针变量p,让指针变量 p 保存变量 b 的内存地址,也就是说 p 指针"指向"变量 b 。程序接着打印 a 变量的值和p 变量的值,分别代表整型变量 a 保存的整数值和指针变量 p 保存的变量 b 的地址值(%p表示用十六进制数字表示地址值)。指针还有特殊的操作:*操作,通过*操作可以访问指针所指向的变量,在程序中也就是说 *p 与变量 b 是等价的,操作变量 *p 就是操作变量 b

类型 变量 特殊操作
int a a (使用 %d 打印)
int * p p (使用 %p 打印) *p (代表指向的变量)

数组

数组是一种特殊的数据类型,它把具有相同类型的若干变量按照有序的顺序组织起来,极大的方便了我们的开发。数组名代表数组的首地址,即数组第一个元素的地址,通过下标 [] 来访问数组里面的元素。

int main() 
{
    int a[5] = {1, 2, 3, 4, 5};
    printf("%d\n", a[0]);
    return 0;
}

上面代码中的 a[0] 代表数组中的第一个元素,输出的结果为1;

数组和指针的联系

其实数组的下标 [] 操作也是一种特殊操作,与指针的 * 操作十分相似。数组名是一个指针:指针常量。它无法改变指向,只能指向数组的首地址,所以a++、a--之类的操作都是错误的(a是数组名)。既然数组名是一个指针,可以使用下标 [] 操作,那么普通的指针变量是不是也可以使用呢?反过来,普通指针的 * 操作是不是也适合数组呢?

int main()
{
    int a[4] = {5, 6, 7, 8};
    int *p = a;
    int i;
    printf("输出数组里面的内容:\n");
    for(i = 0; i < 4; i++)
        printf("a[%d] = %d\t", i, a[i]);
    printf("\n");

    for(i = 0; i < 4; i++)
        printf("p[%d] = %d\t", i, p[i]);
    printf("\n");

    for(i = 0; i < 4; i++)
        printf("*(a+%d)=%d\t", i, *(a+i));
    printf("\n");

    for(i = 0; i < 4; i++)
        printf("*(p+%d)=%d\t", i, *(p+i));
    printf("\n");
    return 0;
}

运行结果:


运行结果

从结果可以看出,[]* 操作都适用于指针变量,数组也是通过操作指针来实现对元素的查询、修改操作。让我们再深入一点,数组是如何通过下标操作找到对应的元素的呢?

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p = a;
    printf("%d\n", p[2]);
    printf("%d\n", *(p+2));

    p = &a[2];
    printf("%d\n", p[0]);
    printf("%d\n", *p);
    return 0;
}

运行一下代码发现,输出的数据都是3,也就是数组中的第三个元素。怎么会这样?

解释:
程序中当指针 p 指向数组的第三个元素的时候,这时候 p[0] 输出的是3,也就是a[2] 的值,那么 p[0] 的操作结果与 *p 的操作结果一致;另外,大家试一试
输出 p[1] 的值,不出所料操作结果应与 *(p+1) 的操作结果一致。发现规律没?[] 操作其实就是 * 操作啊!!!发现新大陆了啊,有没有?

让我们冷静的分析一下: [] 操作和 * 操作实际上都是偏移操作(内存地址偏移),通过当前指针指向的内存地址以及常量来进行地址偏移,最后通过指针的类型解析所指向地址的内容。

那么偏移的单位是多少?这个与指针或者数组的类型有关,比如 int * 类型的指针一次偏移 sizeof(int) 的地址,double * 类型的指针一次偏移 sizeof(double) 的地址。

指针访问数组的方式

  1. 使用 [] 访问。例如 int a; int *p = a;用 p 表示输出 a[2] 的值:p[2] ;如果是这样int a[5]; int *p = &a[2];用 p 表示输出a[3] 的值:p[1]

  2. 使用 * 访问。例如int a[5]; int *p = a;用 p 表示输出 a[2] 的值:*(p+2);如果是这样:int a[5]; int *p = &a[2];用 p 表示输出 a[3] 的值:*(p+1)

思考

知道指针和数组的操作原理后,下面的题你会做吗?

第一题:

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    
    p = &a[2];
    printf("%d\n", p[-2]);
    printf("%d\n", *(p-2));
    return 0;
}

第二题:

int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *ptr = (int *)(&a + 1);
    printf("%d %d\n", *(a+1), *(ptr-1));
    return 0;
}

第二题注意指针的类型变化哦,自己编写运行一下,看结果与自己想的一样吗?
ps: 竟然还能 p[-2],坑爹有没有...

总结

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

推荐阅读更多精彩内容