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

C++ 如果变量a是char,则数组为char*p=&;C+中定义的行为+;,c++,c,arrays,memory-address,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++ +< /P> 显然,我一直在想: char* p = new char[10]; char* p1 = &p; // Is wrong 但是,当一个数组被创建为堆栈空间中的本地数组时,我的

我一直认为:

char a[10];
char* p = &a;
是错误的,应改为以下内容之一:

char a[10];
char* p = a; // OR
char* p = &a[0];
我希望我能在这里找到线索,所以我读到说p=&a;是有效的,它是关于C语言,而不是C++ +< /P> 显然,我一直在想:

char* p = new char[10];
char* p1 = &p; // Is wrong
但是,当一个数组被创建为堆栈空间中的本地数组时,我的直觉似乎认为
a
&a
&a[0]
都是相同的值/地址。我不得不说,我一直在跟踪C++,而不是看到它这样做,这就是为什么当我开始研究C时,我很快就把它称为错误,但是我确信它不是C的(也可以很好地验证它)。我只是想知道C++中是否也是如此,因为在我记忆中C++通常是用另外两种方式之一,这样的方式(如果我的想象力不玩花招)在C.</P>中似乎是这样做的。 编辑:这真是个愚蠢的问题。我的困惑来自于我的Visual Studio编译器在C中编译它,而不是C++,所以我认为这方面的语言有不同。我不会删除这个问题,因为它已经有了答案

char a[10];
char* p = &a;
在C中确实是错误的

特别是(所有引用均参考ISO 9899:1999(C99),所有重点均由我负责):

6.7.8(初始化)/11表示:

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

6.5.16.1(简单分配):

约束

  • 下列情况之一应适用:
    • 左操作数具有限定或非限定算术类型,右操作数具有限定或非限定算术类型 算术类型
    • 左操作数具有结构或联合类型的限定或非限定版本 与权利类型相适应
    • 两个操作数都是指向兼容类型的合格或不合格版本的指针, 并且左边指向的类型具有左边指向的类型的所有限定符 对,
    • 一个操作数是指向对象或不完整类型的指针,另一个是指向对象的指针
      void
      的合格或不合格版本,左侧所指的类型具有所有 右边所指类型的限定符
    • 左操作数是指针,右操作数是空指针常量;或
    • 左操作数的类型为
      \u Bool
      ,右操作数的类型为指针
  • 只有粗体部分适用;我们没有使用任何算术或结构/联合类型,没有
    void
    \u 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中兼容类型的所有声明器规则都是“两个指针类型兼容…”,“两个数组类型兼容…”,“两个函数类型兼容…”,但非数组类型无法与数组类型兼容

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

    5.1.1.3(诊断):

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

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

    在C中确实是错误的

    特别是(所有引用均参考ISO 9899:1999(C99),所有重点均由我负责):

    6.7.8(初始化)/11表示:

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

    6.5.16.1(简单分配):

    约束

  • 下列情况之一应适用:
    • 左操作数具有限定或非限定算术类型,右操作数具有限定或非限定算术类型 算术类型
    • 左操作数具有结构或联合类型的限定或非限定版本 与权利类型相适应
    • 两个操作数都是指向兼容类型的合格或不合格版本的指针, 并且左边指向的类型具有左边指向的类型的所有限定符 对,
    • 一个操作数是指向对象或incom的指针