C 理解和操作指向整数数组的指针
我在以下代码中遇到问题:C 理解和操作指向整数数组的指针,c,arrays,pointers,array-pointer,C,Arrays,Pointers,Array Pointer,我在以下代码中遇到问题: int a[] = {1, 2, 3, 4}; fprintf(stdout, "a : %lu\n" "*a : %d\n" "&a : %ld\n" "**(&a) : %d\n", (unsigned long int)a, *a,
int a[] = {1, 2, 3, 4};
fprintf(stdout,
"a : %lu\n"
"*a : %d\n"
"&a : %ld\n"
"**(&a) : %d\n",
(unsigned long int)a,
*a,
(unsigned long int)&a,
**(&a)
);
输出:
a : 140726063647232
*a : 1
&a : 140726063647232
**(&a) : 1
我知道&a是指向一维数组的指针。And&a的类型为int*[4]。
我不明白**&a:1是怎么来的。&a是指向数组的指针*p获取指针指向的对象,因此*&a获取数组a
作为指针处理的数组退化为指向其第一个元素的指针,因此*a为1
因为*&a只是a,***&a与*a相同,后者是1。&a是指向数组的指针*p获取指针指向的对象,因此*&a获取数组a
作为指针处理的数组退化为指向其第一个元素的指针,因此*a为1
由于*&a只是a,***&a与*a相同,后者为1。另一种查看方法是通过每次地址或取消引用操作后的结果类型。数组访问的一个基本规则是数组指针转换。这适用于任何阵列的访问,但须遵守所列的4个例外情况[C18标准中的3-_Alignofis不再列出] 关键是要理解数组在访问时会被转换为指向第一个元素的指针,该元素会受到有限的异常影响,这在这里并不相关。如果采用数组的地址,则地址与第一个元素的地址相同,但指针的类型完全不同 取消引用a时,将获得第一个元素:
*a - int
**(&a) - int
为什么?*a是偏移量为0的完全去费伦斯运算的缩写,例如.*a+0,相当于索引表示法中的[0]
当您取消对数组int[4]的引用时,您将返回数组:
*(&a) - int[4] -> converted to pointer to first element.
然后,通过的操作,将其转换为指向第一个元素的指针。再次取消引用将获得第一个元素:
*a - int
**(&a) - int
现在值得学习,因为它将在以后为您省去很多困惑。另一种方法是通过每个地址或取消引用操作后的结果类型来查看它。数组访问的一个基本规则是数组指针转换。这适用于任何阵列的访问,但须遵守所列的4个例外情况[C18标准中的3-_Alignofis不再列出] 关键是要理解数组在访问时会被转换为指向第一个元素的指针,该元素会受到有限的异常影响,这在这里并不相关。如果采用数组的地址,则地址与第一个元素的地址相同,但指针的类型完全不同 取消引用a时,将获得第一个元素:
*a - int
**(&a) - int
为什么?*a是偏移量为0的完全去费伦斯运算的缩写,例如.*a+0,相当于索引表示法中的[0]
当您取消对数组int[4]的引用时,您将返回数组:
*(&a) - int[4] -> converted to pointer to first element.
然后,通过的操作,将其转换为指向第一个元素的指针。再次取消引用将获得第一个元素:
*a - int
**(&a) - int
这是值得现在学习的,因为它将节省你很多困惑以后
如果要打印地址,应使用printf或fprintf函数的%p转换说明符。
另一方面,在使用上述相同函数打印整数数据类型时,应使用%d转换说明符。然后您可以省略所有向上转换为无符号长整型的数据类型。
在您的情况下,c数组衰减到相同数据类型的指针并非在所有情况下,数组都可以衰减到指针。在您的打印中,您使用了这个事实,例如,当取消引用数组*a时。c语言中的这一事实使我们能够写出以下语句:
int*a_ptr=a;和int*ptr=&a[0];。现在a_ptr和ptr相等!指向内存中的同一地址。
打印a类似于打印a_ptr值,也类似于打印ptr值。以打印&a[0]结尾。
打印*a类似于打印*a_ptr和打印*ptr,因为ptr=&a[0];然后,*ptr==*&a[0]==a[0],所以简单地说就是a[0],它是1。
priniting&a。现在什么是&a?它是指向整数数组的指针!更精确地说,它是一个指向4个整数的数组的指针,它是int*[4],所以当打印a的地址时,它就像打印*int*[4]的解引用一样,它是简单数组a的地址。请注意,数据类型是不同的!a和a!
打印**&a与**int*[4]与*a相同,后者与*a+0相同,后者与*ptr相同,后者是:a[0]是1。
将代码段修复为:
int a[] = {1, 2, 3, 4};
fprintf(stdout, /*you can use printf instead of fprintf(srdout,)*/
"a : %p\n"
"*a : %d\n"
"&a : %p\n"
"**(&a) : %d\n",
a,
*a,
&a,
**(&a)
);
如果要打印地址,应使用printf或fprintf函数的%p转换说明符。
另一方面,在使用上述相同函数打印整数数据类型时,应使用%d转换说明符。然后您可以省略所有向上转换为无符号长整型的数据类型。
在您的情况下,c数组衰减到相同数据类型的指针并非在所有情况下,数组都可以衰减到指针。在您的打印中,您使用了这个事实,例如,当取消引用数组*a时。c语言中的这一事实使我们能够写出以下语句:
int*a_ptr=a;和int*ptr=&a[0];。现在a_ptr和ptr相等!指向同一个地址,我
n内存。
打印a类似于打印a_ptr值,也类似于打印ptr值。以打印&a[0]结尾。
打印*a类似于打印*a_ptr和打印*ptr,因为ptr=&a[0];然后,*ptr==*&a[0]==a[0],所以简单地说就是a[0],它是1。
priniting&a。现在什么是&a?它是指向整数数组的指针!更精确地说,它是一个指向4个整数的数组的指针,它是int*[4],所以当打印a的地址时,它就像打印*int*[4]的解引用一样,它是简单数组a的地址。请注意,数据类型是不同的!a和a!
打印**&a与**int*[4]与*a相同,后者与*a+0相同,后者与*ptr相同,后者是:a[0]是1。
将代码段修复为:
int a[] = {1, 2, 3, 4};
fprintf(stdout, /*you can use printf instead of fprintf(srdout,)*/
"a : %p\n"
"*a : %d\n"
"&a : %p\n"
"**(&a) : %d\n",
a,
*a,
&a,
**(&a)
);
您应该使用%p作为指针,而不是%lu。如果您对编程语言比较陌生:在C中,数组也是指针。对于基本的语言概念,打字,其他一些语言可能会更好。至少在教育学上。**&a 100%等同于*a,仅此而已。这只是混淆——故意写不好的代码。@Lundin,混淆是故意的,目的是教人去引用和引用。@AnshumanKumar那么为什么它不是写为**&a或**&a呢?前者是最干净的,如果你希望学生不掌握优先级/联想性,后者是有意义的。不过介于两者之间?您应该使用%p作为指针,而不是%lu。如果您对编程语言比较陌生:在C中,数组也是指针。对于基本的语言概念,打字,其他一些语言可能会更好。至少在教育学上。**&a 100%等同于*a,仅此而已。这只是混淆——故意写不好的代码。@Lundin,混淆是故意的,目的是教人去引用和引用。@AnshumanKumar那么为什么它不是写为**&a或**&a呢?前者是最干净的,如果你希望学生不掌握优先级/联想性,后者是有意义的。介于两者之间?