背景:完全的C初学者。。试图搞清楚数组的概念,做了一些小试验,查了一些解释,合成此文。
我们说数组变量相当于常量指针,那么实际它就是常量指针名吗?
简单试验:
1 #include <stdio.h> 2 3 int main() { 4 int a; //声明int变量 5 printf("变量的地址:%p\n",&a); //声明变量时,申请内存地址 6 printf("变量占位:%d\n",sizeof(a)); //根据类型决定分配空间 7 // printf("变量的值:%d\n",a); //报错,因为没有放入值 8 a = 9; 9 printf("变量的值:%d\n\n",a); 10 11 12 int *p; //声明指针变量 13 printf("指针变量的地址:%p\n",&p); 14 printf("指针变量占位:%d\n",sizeof(p)); 15 // printf("指针变量指向:%d\n",*p); //报错,因为没有放入值 16 p = &a; 17 printf("指针变量的值:%p\n",p); 18 printf("指针变量指向:%d\n\n",*p); 19 20 21 int s[4]={5}; //声明数组变量 22 printf("数组变量的地址:%p\n",&s); 23 printf("数组变量的地址+1:%p\n",&s+1); 24 printf("数组变的地址占位:%d\n",sizeof(&s)); //sizeof(地址) 25 printf("数组变量的值:%p\n",s); //数组变量的值的自己的地址!是一个特殊的指针! 26 printf("数组变量的值+1:%p\n",s+1); 27 printf("数组变占位:%d\n",sizeof(s)); //sizeof(地址)? 28 29 30 printf("数组变量首元素的地址:%p\n",&s[0]); //s和s[0]地址相同! 31 printf("数组变量次元素的地址:%p\n",&s[1]); //数组是变量的容器 32 printf("取数组首元素:%d\n",s[0]); 33 printf("对数组变量解指针操作:%d\n",*s); //s指向的东西就是s[0]! 34 printf("数组元素占位:%d\n\n",sizeof(s[0])); 35 36 37 38 //指针变量和数组变量互相s赋值 39 int b=88; 40 int *const p2=&b; //常量指针必须在声明的时候初始化! 41 p = s; //可以改变指针p的值 42 // p2 = p; //常量指针不可修改! 43 // s = &b; //数组变量不可修改! 44 int s2[5]; 45 printf("数组变量s2的地址:%p\n",&s); 46 printf("数组变量的值:%p\n",s); //地址相同?? 47 // s2 = s; //数组变量不可修改! 48 49 return 0; 50 }
输出:
可以看出来:
- 数组变量符合指针的定义
- 数组变量的值就是数组首元素的地址
- 数组变量不可修改,类似于常量指针
其中不解的是
- 用&取数组变量的地址,发现与数组首元素的值的地址相同,即s与&s的值相同。
- 如果数组变量就是指针的话,那么数组变量的值为其首元素的地址,而它自己不应该放在另一个地址吗?(就像上面的指针变量p一样)
于是,查阅了一下,这个问题大致是这样理解的
-
arr 本身是左值(但不可仅凭此表达式修改),指代数组对象。不过 arr 会在大多数场合隐式转换成右值表达式 &(arr[0]) 。为指针类型,指向 arr[0] 。
&arr 是右值表达式,为指针类型,指向 arr 本身。简单来说就是 arr 本身不是地址而是指代整个数组,只不过会隐式转成指针罢了。arr (转换后)和 &arr 类型不同,数值相等是因为 arr 和 arr[0] 地址相同,这里地址指首地址。C作为实用语言,为了使用方便而进行隐式类型转换。【参考知乎-暮无井见铃】 - &arr[0]跟&arr相同是合理的,而arr的值也跟前面两个相同,这更像是强加的语言规定,或者说……语法糖。【参考】
另有一份总结:
- 数组地址与数组名:
- 数组名代表数组首元素的地址(a);
- 数组的地址需要用取地址符&才能得到(&a);
- 数组首元素的地址值与数组的地址值相同
- 数组首元素的地址与数组的地址是两个不同的概念
- 数组名的盲点:
- 数组名可以看做一个常量指针;【可以转换为,执行指针的操作】
- 数组名“指向”的是内存中数组首元素的起始位置;
- 在表达式中数组名只能作为右值使用下
- 下列场合中数组名不能看做常量指针:
- 数组名作为sizeof操作符的参数;【sizeof只做类型推测,不进行计算,因此数组变量不会被转换为指针变量,说明数组变量本身不是指针,可验证sizeof(arr)和sizeof(arr[0]),二者是不同的】
- 数组名作为&运算符的参数;【可验证如下】
验证s与&s类别不同:
s与&s值相同,但s+1与&s+1值不同