数组变量与指针

背景:完全的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 }
View Code

输出:

可以看出来:

  • 数组变量符合指针的定义
  • 数组变量的值就是数组首元素的地址
  • 数组变量不可修改,类似于常量指针

其中不解的是

  • 用&取数组变量的地址,发现与数组首元素的值的地址相同,即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值不同

转载于:https://www.cnblogs.com/Jasonljy/p/10075894.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值