我一直以为:
char a[10];
char* p = &a;
错了,它应该是以下之一:
char a[10];
char* p = a; // OR
char* p = &a[0];
我希望我能找到这里的主题,所以我正在阅读说p =& a;是有效的,它是关于C语言,而不是C ++。
我一直在想,显然:
char* p = new char[10];
char* p1 = &p; // Is wrong
但是当一个数组在堆栈空间中创建为本地时,我的直觉似乎是合理的,a
,&a
和&a[0]
都是相同的值/地址。我不得不说,我一直在关注大多数C ++并且没有看到它以这种方式完成,这就是为什么当我开始调查CI时很快就称它为错误,但我确定它是' ; s不在C中(对此的验证也将受到赞赏)。我只是想知道C ++中的情况是否也是如此,因为据我所知,在C ++中我通常会采用其他两种方式中的一种方式(如果我的想象力不是耍花招) )似乎在C中完成。
编辑:这是一个非常愚蠢的问题。我的困惑来自于我的Visual Studio编译器在C中编译它,但不是在C ++中编译,所以我认为在这方面语言有所不同。我不会删除这个问题,因为它已经有了答案。
答案 0 :(得分:5)
char a[10];
char* p = &a;
在C中确实是错误的。
特别是(所有引用都参考ISO 9899:1999(C99),所有重点都是我的):
6.7.8(初始化)/ 11说:
标量的初始值设定项应为单个表达式,可选择用大括号括起来。该 对象的初始值是表达式的初始值(转换后); 相同的类型 适用于简单赋值的约束和转换,采用标量的类型 成为其声明类型的不合格版本。
6.5.16.1(简单分配):
<强>约束
- 以下其中一项应持有:
- 左操作数具有限定或非限定算术类型,右边有 算术类型;
- 左操作数具有结构或联合类型的限定或非限定版本 兼容权利的类型;
- 两个操作数都指向兼容类型的合格或非限定版本, 并且左边指向的类型具有指向的类型的所有限定符 权;
- 一个操作数是指向对象或不完整类型的指针,另一个是指向a的指针
void
的限定或非限定版本,左侧指向的类型全部 右边指出的类型的限定符;- 左操作数是指针,右边是空指针常量;或
- 左操作数的类型为
_Bool
,右侧为指针。
只有粗体部分适用;我们没有使用任何算术或结构/联合类型,没有void
或_Bool
,也没有空指针常量。
有问题的类型是左侧的char *
(指向char
的指针),右侧是char (*)[10]
(指向char
的数组[10]的指针)。指针类型的兼容性定义如下:
6.7.5.1(指针声明符)/ 2:
要使两个指针类型兼容,两者都应具有相同的限定条件且两者都必须 是兼容类型的指针。
指向类型分别为char
和char [10]
。
但现在我们陷入了困境。有6.2.7(兼容型和复合型)/ 1:
如果类型相同,则两种类型具有兼容类型。附加规则 确定两种类型是否兼容在6.7.2中描述了类型说明符, 在6.7.3中用于类型限定符,在6.7.5中用于声明符。
char
和char [10]
显然不一样。 6.7.5中兼容类型的所有声明符规则都说&#34; 要使两个指针类型兼容... &#34;,&#34; 对于两种数组类型来说是兼容的...... &#34;,&#34; 要兼容两种功能类型... &#34;,但是没有办法让非数组类型与数组类型兼容。
因此,类型不兼容,char *p = &a
违反了6.5.16.1中的约束。
5.1.1.3(诊断):
符合要求的实施应至少产生一条诊断信息(在 实现定义的方式)如果预处理翻译单元或翻译单元 包含违反任何语法规则或约束的行为,即使行为也是明确的 指定为未定义或实现定义。
这意味着需要警告或错误消息。如果您的编译器没有生成一个,那么它不是一个真正的C编译器。