[英]If variable a is a char array is char* p = &a defined behaviour in C++
我一直认为:
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时很快将其称为错误,但是我确信它不在C中(很好的验证对此也将不胜感激)。 我只是想知道在C ++中是否也是如此,因为据我所记得,在C ++中通常是另外两种方式之一,而这种方式(如果我的想象力不是很强的话)似乎是在C中完成的。
编辑:这是一个非常愚蠢的问题。 我的困惑来自于我的Visual Studio编译器使用C编译而不是C ++编译的事实,因此我认为这方面的语言有所不同。 我不会删除该问题,因为它已经有了答案。
char a[10];
char* p = &a;
在C中确实是错误的。
特别是(所有引用均参考ISO 9899:1999(C99),并且所有强调均归我所有):
6.7.8(初始化)/ 11说:
标量的初始化程序应为单个表达式,可以选择用大括号括起来。 对象的初始值是表达式的初始值(转换后); 应用与简单赋值相同的类型约束和转换 ,将标量的类型作为其声明类型的非限定版本。
6.5.16.1(简单分配):
约束条件
- 以下条件之一应成立:
- 左操作数具有合格或不合格的算术类型,而右具有算术类型;
- 左操作数具有与右类型兼容的结构或联合类型的合格或不合格版本;
- 这两个操作数都是指向兼容类型的合格或不合格版本的指针 ,并且左侧指向的类型具有右侧指向的类型的所有限定符;
- 一个操作数是指向对象或不完整类型的指针,另一个是指向
void
的合格或不合格版本的指针,并且左侧指向的类型具有右侧指向的所有类型的限定符;- 左边的操作数是指针,右边的是空指针常量; 要么
- 左操作数的类型为
_Bool
,右为指针。
仅黑体部分适用; 我们没有使用任何算术或struct / union类型,没有void
或_Bool
,也没有null指针常量。
有问题的类型在左边是char *
(指向char
指针),在右边是char (*)[10]
(指向char
array [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中兼容类型的声明器规则都说“ 使两个指针类型兼容... ”,“ 使两个数组类型兼容... ”,“ 使两个函数类型兼容... ” ,但是非数组类型无法与数组类型兼容。
因此,这些类型不兼容,并且char *p = &a
违反了6.5.16.1中的约束。
5.1.1.3(诊断):
如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的条件 ,即使该行为也被明确指定为未定义或实现,则符合条件的实现应至少产生一条诊断消息 (以实现定义的方式标识)定义。
这意味着需要警告或错误消息。 如果您的编译器不生成一个,则它不是实际的C编译器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.