简体   繁体   English

如果变量a是char数组,则char * p =&a在C ++中定义的行为

[英]If variable a is a char array is char* p = &a defined behaviour in C++

I've always thought that: 我一直认为:

char a[10];
char* p = &a;

Is wrong and that it should be one of the following instead: 是错误的,应改为以下之一:

char a[10];
char* p = a; // OR
char* p = &a[0];

I wish I could find the thread here on SO I was reading saying that p = &a; 我希望我可以在这里找到线程,所以我正在阅读说p =&a;。 is valid, and it was in regard to the C language, not C++. 是有效的,并且是针对C语言而不是C ++。

I've been thinking, obviously: 我一直在思考,显然:

char* p = new char[10];
char* p1 = &p; // Is wrong

But when an array is created as a local in stack space it seems reasonable to my intuition that a , &a , and &a[0] are all the same value/address. 但是,当在堆栈空间中将数组创建为局部数组时,根据我的直觉, a&a&a[0]都具有相同的值/地址似乎是合理的。 I have to say, I've been following mostly C++ and not seen it done this way, which is why when I started to look into CI was quick to call it an error, but I'm sure it's not in C (well verification on that would be appreciated also). 我不得不说,我一直都在关注C ++,但并没有看到它是通过这种方式完成的,这就是为什么当我开始研究CI时很快将其称为错误,但是我确信它不在C中(很好的验证对此也将不胜感激)。 I'm just wondering if it's also the case in C++, because as far as I remember in C++ is usually done one of the other two ways and this way (if my imagination isn't playing tricks) seems to done in C. 我只是想知道在C ++中是否也是如此,因为据我所记得,在C ++中通常是另外两种方式之一,而这种方式(如果我的想象力不是很强的话)似乎是在C中完成的。

Edit: This is a really dumb question. 编辑:这是一个非常愚蠢的问题。 My confusion came from the fact that my Visual Studio compiler compiles it in C, but not for C++, so I thought there was a difference in the language in this respect. 我的困惑来自于我的Visual Studio编译器使用C编译而不是C ++编译的事实,因此我认为这方面的语言有所不同。 I won't delete the question because it already has an answer. 我不会删除该问题,因为它已经有了答案。

char a[10];
char* p = &a;

is indeed wrong in C. 在C中确实是错误的。

In particular (all quotes refer to ISO 9899:1999 (C99) and all emphasis is mine): 特别是(所有引用均参考ISO 9899:1999(C99),并且所有强调均归我所有):

6.7.8 (Initialization) / 11 says: 6.7.8(初始化)/ 11说:

The initializer for a scalar shall be a single expression, optionally enclosed in braces. 标量的初始化程序应为单个表达式,可以选择用大括号括起来。 The initial value of the object is that of the expression (after conversion); 对象的初始值是表达式的初始值(转换后); the same type constraints and conversions as for simple assignment apply , taking the type of the scalar to be the unqualified version of its declared type. 应用与简单赋值相同的类型约束和转换 ,将标量的类型作为其声明类型的非限定版本。

6.5.16.1 (Simple assignment): 6.5.16.1(简单分配):

Constraints 约束条件

  1. One of the following shall hold: 以下条件之一应成立:
    • the left operand has qualified or unqualified arithmetic type and the right has arithmetic type; 左操作数具有合格或不合格的算术类型,而右具有算术类型;
    • the left operand has a qualified or unqualified version of a structure or union type compatible with the type of the right; 左操作数具有与右类型兼容的结构或联合类型的合格或不合格版本;
    • both operands are pointers to qualified or unqualified versions of compatible types , and the type pointed to by the left has all the qualifiers of the type pointed to by the right; 这两个操作数都是指向兼容类型的合格或不合格版本的指针 ,并且左侧指向的类型具有右侧指向的类型的所有限定符;
    • one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void , and the type pointed to by the left has all the qualifiers of the type pointed to by the right; 一个操作数是指向对象或不完整类型的指针,另一个是指向void的合格或不合格版本的指针,并且左侧指向的类型具有右侧指向的所有类型的限定符;
    • the left operand is a pointer and the right is a null pointer constant; 左边的操作数是指针,右边的是空指针常量; or 要么
    • the left operand has type _Bool and the right is a pointer. 左操作数的类型为_Bool ,右为指针。

Only the bold part applies; 仅黑体部分适用; we're not using any arithmetic or struct/union types, there's no void or _Bool and no null pointer constants. 我们没有使用任何算术或struct / union类型,没有void_Bool ,也没有null指针常量。

The types in question are char * (pointer to char ) on the left and char (*)[10] (pointer to array[10] of char ) on the right. 有问题的类型在左边是char * (指向char指针),在右边是char (*)[10] (指向char array [10]的指针)。 Compatibility of pointer types is defined as follows: 指针类型的兼容性定义如下:

6.7.5.1 (Pointer declarators) / 2: 6.7.5.1(指针声明符)/ 2:

For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types . 为了使两个指针类型兼容,两者都应具有相同的资格,并且都应是指向兼容类型的指针

The pointed-to types are char and char [10] , respectively. 指向的类型分别是charchar [10]

But now we're stuck. 但是现在我们被困住了。 There is 6.2.7 (Compatible type and composite type) / 1: 有6.2.7(兼容类型和复合类型)/ 1:

Two types have compatible type if their types are the same. 如果两个类型相同,则它们具有兼容类型 Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.5 for declarators. 用于确定两种类型是否兼容的其他规则,在6.7.2中针对类型说明符进行了描述,在6.7.3中针对类型限定符进行了说明,在6.7.5中针对声明符进行了描述。

char and char [10] are clearly not the same. charchar [10]显然不同。 All the declarator rules for compatible types in 6.7.5 say " For two pointer types to be compatible ... ", " For two array types to be compatible ... ", " For two function types to be compatible ... ", but there is no way for a non-array type to be compatible with an array type. 所有在6.7.5中兼容类型的声明器规则都说“ 使两个指针类型兼容... ”,“ 使两个数组类型兼容... ”,“ 使两个函数类型兼容... ” ,但是非数组类型无法与数组类型兼容。

Thus the types are not compatible and char *p = &a violates a constraint in 6.5.16.1. 因此,这些类型不兼容,并且char *p = &a违反了6.5.16.1中的约束。

5.1.1.3 (Diagnostics): 5.1.1.3(诊断):

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint , even if the behavior is also explicitly specified as undefined or implementation-defined. 如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的条件 ,即使该行为也被明确指定为未定义或实现,则符合条件的实现应至少产生一条诊断消息 (以实现定义的方式标识)定义。

This means a warning or error message is required. 这意味着需要警告或错误消息。 If your compiler doesn't produce one, it's not an actual C compiler. 如果您的编译器不生成一个,则它不是实际的C编译器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM