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

时间:2018-03-06 23:46:39

标签: c++ c arrays memory-address

我一直以为:

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 ++中编译,所以我认为在这方面语言有所不同。我不会删除这个问题,因为它已经有了答案。

1 个答案:

答案 0 :(得分:5)

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

在C中确实是错误的。

特别是(所有引用都参考ISO 9899:1999(C99),所有重点都是我的):

6.7.8(初始化)/ 11说:

  

标量的初始值设定项应为单个表达式,可选择用大括号括起来。该   对象的初始值是表达式的初始值(转换后); 相同的类型   适用于简单赋值的约束和转换,采用标量的类型   成为其声明类型的不合格版本。

6.5.16.1(简单分配):

  

<强>约束

     
      
  1. 以下其中一项应持有:      
        
    • 左操作数具有限定或非限定算术类型,右边有   算术类型;
    •   
    • 左操作数具有结构或联合类型的限定或非限定版本   兼容权利的类型;
    •   
    • 两个操作数都指向兼容类型的合格或非限定版本,   并且左边指向的类型具有指向的类型的所有限定符   权;
    •   
    • 一个操作数是指向对象或不完整类型的指针,另一个是指向a的指针   void的限定或非限定版本,左侧指向的类型全部   右边指出的类型的限定符;
    •   
    • 左操作数是指针,右边是空指针常量;或
    •   
    • 左操作数的类型为_Bool,右侧为指针。
    •   
  2.   

只有粗体部分适用;我们没有使用任何算术或结构/联合类型,没有void_Bool,也没有空指针常量。

有问题的类型是左侧的char *(指向char的指针),右侧是char (*)[10](指向char的数组[10]的指针)。指针类型的兼容性定义如下:

6.7.5.1(指针声明符)/ 2:

  

要使两个指针类型兼容,两者都应具有相同的限定条件且两者都必须   是兼容类型的指针

指向类型分别为charchar [10]

但现在我们陷入了困境。有6.2.7(兼容型和复合型)/ 1:

  

如果类型相同,则两种类型具有兼容类型。附加规则   确定两种类型是否兼容在6.7.2中描述了类型说明符,   在6.7.3中用于类型限定符,在6.7.5中用于声明符。

charchar [10]显然不一样。 6.7.5中兼容类型的所有声明符规则都说&#34; 要使两个指针类型兼容... &#34;,&#34; 对于两种数组类型来说是兼容的...... &#34;,&#34; 要兼容两种功能类型... &#34;,但是没有办法让非数组类型与数组类型兼容。

因此,类型不兼容,char *p = &a违反了6.5.16.1中的约束。

5.1.1.3(诊断):

  

符合要求的实施应至少产生一条诊断信息(在   实现定义的方式)如果预处理翻译单元或翻译单元   包含违反任何语法规则或约束的行为,即使行为也是明确的   指定为未定义或实现定义。

这意味着需要警告或错误消息。如果您的编译器没有生成一个,那么它不是一个真正的C编译器。