【发布时间】:2020-05-07 22:22:02
【问题描述】:
有这个:
#include <stdio.h>
#include <stdlib.h>
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*(ar+1) = &foo;
ar[1]->c = 'c'; //this work
(*(*ar+1)).c = 'c'; //this does't work
return 0;
}
//(**(ar+1)).c='c'; --> first case
为什么上面的方法只适用于带有数组条目的变体而不是指针解引用?
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*ar=malloc(0);
*(ar+1) = &foo;
//(**(ar+1)).c='c';
(*(*ar+1)).c='c'; // NOW IT WORKS --> second case
printf("%c\n", (*(*ar+1)).c); //prints 'c'
return 0;
}
现在甚至分配了 0 个字节,这没关系,因为我只想要操作系统提供的地址以便初始化第一个元素
问题:指针算法在这两种情况下是如何工作的? 据我了解:
1) 首先为了得到struct Test的左值,指针直接从ar指向的地址指向**ar的左值-sizeof(struct Test**)
2) 在第二种情况下,指针确实初始化了第一个成员ar[0],因此它从*ar 开始,并通过*ar - sizeof(struct Test*) 到达左值。
但是两个指针的大小相同sizeof(struct Test**) == sizeof(struct Test*),因此在算术上应该没有区别,或者我错过了什么?
【问题讨论】:
-
见C Operator Precedence,
'*'的优先级高于'+'那么(*(*ar+1)).c发生了什么? -
使用索引符号“this work”是
ar[1][0].c = 'c';,“this doesn't work”是ar[0][1].c = 'c',这不起作用,因为您从未为ar[0]设置值。在第二种情况下,您会导致未定义的行为,但有时会表现为似乎在做您期望的事情
标签: c pointers initialization undefined-behavior pointer-arithmetic