Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中解引用运算符(“*”)的混淆_C_Arrays_Dereference - Fatal编程技术网

C语言中解引用运算符(“*”)的混淆

C语言中解引用运算符(“*”)的混淆,c,arrays,dereference,C,Arrays,Dereference,据我所知,撤销限制运算符*返回存储在指针地址中的值。令我困惑的是,运算符与数组指针一起使用时的行为。比如说, int a[4][2]; 然后a在内部被转换为2个整数的4个元素数组的第一个元素的指针。那么*a返回哪个值?我真的很困惑 a的类型是int[4][2],因此*a(或相当于a[0])的类型是int[2] 它与a[0][0]不同。如果您这样做: int a[4][2]; printf("%d\n",*a); 编译器将告诉您: 警告:格式“%d”要求类型为“int”,但参数2的类型为“in

据我所知,撤销限制运算符
*
返回存储在指针地址中的值。令我困惑的是,运算符与数组指针一起使用时的行为。比如说,

int a[4][2];

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

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
,这是:

int a[4][2];
定义的
a
由4个元素组成的数组,每个元素都是由2个
int
元素组成的数组。(二维数组只不过是数组的数组。)

在大多数上下文中,数组表达式隐式转换为指向数组对象初始(第零个)元素的指针。(请注意,假设存在一个数组对象;这引起了一些担忧,但与此无关。)

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

  • 当它是
    sizeof
    的操作数时
  • 当它是一元
    的操作数时;及
  • 当它是用于初始化数组对象的初始值设定项中的字符串文字时
(特定于编译器的扩展,如gcc的
typeof
可能会创建更多的异常。)

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

但我们还没有完成
*a
也是数组类型的表达式,这意味着,根据它的使用方式,它可能会再次转换为指针,这次是
int*
类型

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

如果我们编写
**a
,则会发生转换<代码>*a
类型为
int[2]
,转换为
int*
;产生类型为
int
的表达式的解引用

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

隐式数组到指针的转换规则见第6.3.2.1节第3段。(该段错误地将
\u Alignof
作为第四个例外,但
\u Alignof
不能应用于表达式。已发布的C11标准更正了该错误。)


推荐阅读:.

的第6节如果您对引用
int*
的错误消息感到困惑,这是因为在
&
sizeof
或相关类型查询以外的任何上下文中,数组类型的表达式都会隐式转换为指针。所以
int[2]
变成了
int*
@chrisdd:“相关类型查询”是什么意思?数组表达式转换为指针,除非它是(a)一元
的操作数,(b)大小
的操作数,或(c)用于初始化数组(子)对象的初始值设定项中的字符串文字。这些是唯一的例外。(C11的N1570草稿错误地列出了第四个,但
\u Alignof
运算符不能应用于表达式。)@KeithThompson:
decltype
typeof
Alignof
存在于各种扩展中,以及
\u Generic
。也可能是
offset of
,但在这种情况下,转换为指针将无效。实际上
\u Generic
的第一个操作数如果是数组类型,则会转换为指针。(gcc同意;至少从3.7.1版开始,clang不同意。)
offsetof()
不能将数组表达式作为参数,因此它不适用。扩展可能是另一回事。在“如果我们写sizeof*a,转换就不会发生”这句话中,转换是指从2整数数组到指向2整数数组初始元素的指针吗?另外,我认为下一段应该编辑为“*a是int型[2],转换为int”
*a
没有int(*)型[2]
;它的类型是
int[2]
@jwqwerty:是的,
*a
int[2]
int*
的转换没有发生。我已经相应地更新了我的答案——关于
*a
的类型,您是对的。没有“指向数组的指针”。数组不是指针。“然后,
a
被内部转换为2整数的4个元素数组的第一个元素的指针。”这显然是错误的@Olaf没有指向数组的指针是什么意思?这(int(*x)[4][2])不是意味着x是指向一个由4个元素组成的2 int数组的指针吗?@Olaf对不起,我还是不明白!那么,如果“a”没有在内部转换为指向初始元素的指针,那么“*a”应该如何解释呢?真的吗??你认为<代码> < <代码>是吗?