以下程序打印a和数组共享相同的地址。 我该如何理解这种行为? 是& arr指针arr的地址,它包含起始地址10个字符?
#include <stdio.h>
int main()
{
char arr[10] = {0};
char* a = (char*)(&arr);
*a = 1;
printf("a=%p,arr=%p.\n", a, arr);
printf("%d\n", arr[0]);
return 0;
}
答案 0 :(得分:2)
在C中分配数组时,得到的结果如下:
+---+
arr[0]: | |
+---+
arr[1]: | |
+---+
...
+---+
arr[N-1]: | |
+---+
就是这样。没有为名为arr
的对象留出单独的内存位置来存储数组的第一个元素的地址。因此,数组的第一个元素(&arr[0]
)的地址与数组本身的地址(&arr
)是相同的值。
除非它是sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,表达式为类型“{元素数组T
”将被转换(“衰减”)为“指向T
的指针”类型的表达式,表达式的值将是第一个元素的地址数组。
因此,第一个arr
调用中的表达式printf
的类型为char [10]
;根据上述规则,表达式“衰减”为char *
类型,值为arr[0]
的地址。
在表达式&arr
中,arr
是一元&
运算符的操作数,因此不应用转换;而不是获得类型char **
的表达式,而是获得类型为char (*)[10]
的表达式(指向char
的10元素数组的指针)。同样,由于数组的第一个元素的地址与整个数组的地址相同,因此表达式arr
和&arr
具有相同的值。
答案 1 :(得分:1)
在惯用语C中,您应该写char *a = arr;
或char *a = &(arr[0]);
。 &arr
通常为char **
。即使现代(C ++)编译器自动修复它,它也不正确。
由于arr
是char
的数组,arr[0]
是char
,而arr与&(arr[0])
相同,因此它是char *
}。如果你习惯了其他语言可能会很奇怪,但这就是C的工作原理。如果arr是包含struct
的任何其他类型的数组,那将是相同的。
答案 2 :(得分:0)
arr
和a
打印的地址是数组arr
的第一个元素的内存地址。 (请记住,数组的名称始终是指向该数组的第一个元素的指针。)这是因为在定义了数组arr
之后,将a
定义为指向同一地址的指针在记忆中。
答案 3 :(得分:0)
根据C标准(6.3.2.1 Lvalues,数组和函数指示符)
3除非它是sizeof运算符或一元&amp;的操作数。 operator,或者是用于初始化数组的字符串文字,a 具有类型''数组类型''的表达式将转换为 带有''指向类型'的指针的表达式,指向初始值 数组对象的元素,而不是左值。如果是数组对象 具有寄存器存储类,行为未定义。
数组的地址是其第一个元素的地址。所以虽然这些类型不同
char ( * )[10]
(对应于&amp; arr)和char *
(在演员声明中使用)
char * a =(char *)(&amp; arr); )它们将具有与数组第一个元素的地址相同的值。
如果你不使用强制转换,那么由expression&amp; arr初始化的指针的正确定义将是
char ( *a )[10] = &arr;
看到差异然后指针递增。对于指针a的定义,表达式++a
的值将比初始值更大sizeof( char)
。对于指针,我展示了表达式++ a的值将比初始值更大10 * sizeof( char )
。
在您的情况下,表达式*a
的类型为char
,您可以编写*a = 1;
,而在我的情况下,表达式*a
的类型将为char[10]
你可能不会写*a = 1;