据我所知,derefence运算符*
返回存储在指针地址中的值。我感到困惑的是操作符与数组指针一起使用时的行为。例如,
int a[4][2];
然后a
在内部转换为2个整数的4个元素的数组的第一个元素的指针。然后*a
返回哪个值?我真的很困惑!
答案 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部分。