关于C中的解引用运算符(" *")的混淆

时间:2016-08-06 00:56:39

标签: c arrays dereference

据我所知,derefence运算符*返回存储在指针地址中的值。我感到困惑的是操作符与数组指针一起使用时的行为。例如,

int a[4][2];

然后a在内部转换为2个整数的4个元素的数组的第一个元素的指针。然后*a返回哪个值?我真的很困惑!

2 个答案:

答案 0 :(得分:9)

a的类型为int[4][2],因此*a(或等效a[0])的类型为int[2]

a[0][0]相同。如果你这样做:

int a[4][2];
printf("%d\n",*a);

编译器会告诉你:

  

警告:格式'%d'需要类型'int',但参数2的类型为'int *'

由于数组(在这种情况下是类型int [2]之一)被传递给一个函数,它会衰减到指向此上下文中第一个元素的指针。

另一方面,如果您有**a,则相当于a[0][0]并且类型为int

答案 1 :(得分:6)

此:

int a[4][2];

定义a一个包含4个元素的数组,每个元素都是2 int个元素的数组。 (二维数组不过是数组数组。)

在大多数情况下,数组表达式被隐式转换为指向数组对象的初始(第0个)元素的指针。 (注意假设有一个数组 object ;这引起了一些焦虑,但它在这里并不相关。)

数组表达式转换为指针的情况为:

  • 当它是sizeof;
  • 的操作数时
  • 当它是一元&的操作数时;和
  • 当用于初始化数组对象的初始值设定项中的字符串文字时。

(gcc' s typeof等特定于编译器的扩展程序可能会产生更多异常。)

因此,在表达式*a中,子表达式a(类型为int[4][2])被隐式转换为类型为int(*)[2]的指针(指向数组的指针2) int S)。应用一元*取消引用指针,为我们提供int[2]类型的表达式。

但我们尚未完成*a也是数组类型的表达式,这意味着,根据它的使用方式,它将可能再次转换为指针,此时类型为{{ 1}}。

如果我们写int*,子表达式sizeof *a将从a转换为int[4][2],但子表达式int(*)[2] 不是*a转换为int[2],因此表达式会产生int*类型的大小。

如果我们写int[2],则转换会发生**a的类型为*a,转换为int[2];取消引用会产生类型为int*的表达式。

请注意,尽管我们可以合法地引用int,但是使用两个指针取消引用操作,没有指针对象**a是一个数组对象,完全由8个a个对象组成。隐式转换产生指针

隐式数组到指针转换规则在N1570第6.3.2.1节第3段中。(该段错误地将int作为第四个例外,但_Alignof无法应用发表的C11标准更正了错误。)

推荐阅读:comp.lang.c FAQ的第6部分。