C语言-数组指针

数组指针

指针数组和数组指针常常让人感到混淆。

从词性的角度理解。指针数组是指针修饰数组,强调的是数组。数组指针是数组修饰指针,强调的是指针。

从C语法定义来看:二者定义的语法不同。如果int (*p)[5] 不加括号,就变成了指针数组int *p[5]。

int main() {
	int array[5] = { 1, 2, 3, 4, 5 };
    int* arr[5];  // 指针数组。数组arr中存储的都是int型的指针
    int (*p)[5];  // 数组指针p。指针p指向一个长度为5个int的数组首地址
    p = (int(*)[5])arr;  // 数组指针p指向arr的首地址

    printf("%d %d\n", p, *p);
    
    return 0;
}
输出:
    11533108 11533108

从汇编代码看:注意默认是cdel调用约定,printf的参数是从右往左压栈。可以看到p和*p的值都是来自[ebp-44h]。因此对于cup而言,二者是没有区别的。

我认为p和*p是编译器用于某种区分的。

printf("%d %d\n", p, *p);
006450D8 8B 45 BC             mov         eax,dword ptr [ebp-44h]  
006450DB 50                   push        eax  
006450DC 8B 4D BC             mov         ecx,dword ptr [ebp-44h]  
006450DF 51                   push        ecx  
006450E0 68 DC 7B 64 00       push        647BDCh  
006450E5 E8 C7 C2 FF FF       call        006413B1  
006450EA 83 C4 0C             add         esp,0Ch  

验证我的假设

int main() {

	int arr[5] = { 1, 2, 3, 4, 5 };
	int(*p)[2] = (int(*) [2])arr;

	printf("%d %d\n", p, *p);

	printf("%d %d %d\n", p, p+1, *(*(p+1)));

	printf("%d %d %d\n", *p, (*p)+1, *(((*p)+1)+0));

	return 0;

}
输出:
5241652 5241652
5241652 5241660 3
5241652 5241656 2
printf("%d %d %d\n", p, p + 1, *(*(p + 1)));
00D450ED B8 04 00 00 00       mov         eax,4  
00D450F2 6B C8 00             imul        ecx,eax,0  
00D450F5 8B 55 D8             mov         edx,dword ptr [ebp-28h]  
00D450F8 8B 44 0A 08          mov         eax,dword ptr [edx+ecx+8]  ; +8
00D450FC 50                   push        eax  
00D450FD 8B 4D D8             mov         ecx,dword ptr [ebp-28h]  
00D45100 83 C1 08             add         ecx,8  ;  p + 1 --> +8
00D45103 51                   push        ecx  
00D45104 8B 55 D8             mov         edx,dword ptr [ebp-28h]  
00D45107 52                   push        edx  
00D45108 68 E4 7B D4 00       push        0D47BE4h  
00D4510D E8 9F C2 FF FF       call        00D413B1  
00D45112 83 C4 10             add         esp,10h  


	printf("%d %d %d\n", *p, (*p)+1, *(((*p)+1)+0));
00D45115 8B 45 D8             mov         eax,dword ptr [ebp-28h]  
00D45118 8B 48 04             mov         ecx,dword ptr [eax+4]  ; +4
00D4511B 51                   push        ecx  
00D4511C 8B 55 D8             mov         edx,dword ptr [ebp-28h]  
00D4511F 83 C2 04             add         edx,4  ; (*p)+1 --> +4
00D45122 52                   push        edx  
00D45123 8B 45 D8             mov         eax,dword ptr [ebp-28h]  
00D45126 50                   push        eax  
00D45127 68 E4 7B D4 00       push        0D47BE4h  
00D4512C E8 80 C2 FF FF       call        00D413B1  
00D45131 83 C4 10             add         esp,10h  

实验结果证明:

  1. p和*p存储的值相等

  2. p+1和*p+1的值不相等。

    p+1:5241652 - 5241660 = 8 --> 2个int

    *p+1:5241652 - 5241656 = 4 --> 1个int

    证明p和*p的数据宽度不同。p是2个int宽度,*p是1个int宽度。表明:p指向的是arr首地址,是一个具有2个int宽度的数组的首地址。*p指向arr数组第一个元素的地址,其宽度是1个int宽度。

  3. *(*(p+1))。p+1使得p向高地址移动1*2个int宽度。*(p+1)将移动宽度变为1个int宽度。*(*(p+1))取出指向地址的值:3。*(*(p+1)) == *(*(p+1)+0) == *(p+1)[0]

    *(((*p)+1)+0)。*p将移动宽度变为1个int宽度。(*p)+1使得p向高地址移动1*1个int宽度。((*p)+1)+0使得p向高地址移动0*1个int宽度。*(((*p)+1)+0)取出指向地址的值:2。*(((*p)+1)+0) == *((*p)+1+0) == ((*p)+1)[0]

结论:

数组指针中,p和*p存储的值相等,是编译器用于区分不同数据宽度的一种标记方式。即p指向的是数组首地址,加减运算是按照数组宽度计算。*p指向数组的第一个元素的地址,加减运算是按照数组元素的宽度计算。

鄙人陋见,批评指正!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值