C语言 理解和操作指向整数数组的指针



我在使用以下代码时遇到问题:

int a[] = {1, 2, 3, 4};

fprintf(stdout,
"a      : %lun"
"*a     : %dn"
"&a     : %ldn"
"**(&a) : %dn",
(unsigned long int)a,
*a,
(unsigned long int)&a,
**(&a)
);

输出:

a      : 140726063647232
*a     : 1
&a     : 140726063647232
**(&a) : 1

我知道&a是指向 1 D 数组的指针。而&a的类型是int (*)[4]。 我对怎么**(&a): 1感到困惑.

&a是指向数组的指针。*p获取指针指向的内容,因此*&a获取数组,a

被视为指针的数组退化为指向其第一个元素的指针,因此*a1

由于*&a只是a**&a*a相同,后者1

查看它的另一种方法是通过每个地址取消引用操作后的结果类型。数组访问的基本规则是数组指针转换。C11 标准 - 6.3.2.1 其他操作数 - 适用于访问任何数组的左值、数组和函数指示符 (p3((受列出的 4 个例外 [C18 标准中的 3 个 - 不再列出_Alignof](。

关键是要理解数组在访问时被转换为指向第一个元素的指针(受有限例外限制 - 此处无关(。如果采用数组的地址,则地址与第一个元素的地址相同,但指针的类型完全不同

a   - pointer to int
&a   - pointer-to-array int[4], proper type: int (*)[4]

当你取消引用a时,你会得到第一个元素:

*a   - int

为什么?*a是偏移量为0的完全取消引用操作的缩写,例如*(a + 0)等效于索引表示法中的a[0]

当您取消引用指向数组的指针int[4]时,您会恢复数组:

*(&a)   - int[4] -> converted to pointer to first element.

然后,通过操作,将6.3.2.1(p3(转换为指向第一个元素的指针。再次取消引用,你会得到第一个元素:

**(&a)   - int

现在值得学习,因为它会让你以后省去很多困惑。

  1. 如果你想打印一个address,你可以使用printffprintf函数的%p转换说明符。
  2. 另一方面,使用上述相同功能打印integer data type,应使用%d转换说明符。 然后,您可以省略所有向上转换以unsigned long int数据类型。
  3. 在您的情况下,c arrays衰减到相同数据类型的指针(并非在所有情况下数组都可以decays指针(。 在您的打印中,您使用了这一事实,例如,当取消引用数组时*a. C中的这个事实使我们能够扭动下面的陈述:int* a_ptr = a;int* ptr = &a[0];.现在a_ptrptr是平等的!指向内存中的同一地址。
  4. 打印a就像打印a_ptr值和打印ptr值一样。 以打印&a[0]结束。
  5. 打印*a就像打印 *a_ptr 和打印*ptr,既然ptr = &a[0];那么,*ptr==*&a[0]==a[0]所以简单来说,它的a[0]1
  6. &a. 现在什么是&a? 它是指向整数数组的指针! 更准确地说,它是一个指向 4 个整数数组的指针,这是int (*)[4]所以在打印 a 的地址时,就像打印*(int (*)[4])的取消引用一样,这是数组简单a的地址。 请注意,数据类型是不同的!a&a
  7. 打印**(&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      : %pn"
"*a     : %dn"
"&a     : %pn"
"**(&a) : %dn",
a,
*a,
&a,
**(&a)
);

相关内容

  • 没有找到相关文章

最新更新