【问题标题】:Redefinition allowed in C but not in C++?在 C 中允许重定义,但在 C++ 中不允许?
【发布时间】:2011-07-17 06:43:15
【问题描述】:

为什么这段代码在 C 中有效,而在 C++ 中无效?

int i = 5;
int i; // but if I write int i = 5; again I get error in C also

int main(){

  // using i
}

【问题讨论】:

    标签: c++ c declaration


    【解决方案1】:

    Tentative definition is allowed in C but not in C++.

    暂定定义是没有存储类说明符和初始化器的任何外部数据声明。

    C99 6.9.2/2

    为具有文件范围没有初始化程序的对象声明标识符,以及 没有存储类说明符或带有存储类说明符静态,构成一个 暂定定义。如果一个翻译单元包含一个或多个暂定定义 标识符,并且翻译单元不包含该标识符的外部定义,则 该行为就像翻译单元包含该文件的文件范围声明一样 标识符,具有作为翻译单元末尾的复合类型,具有初始值设定项 等于 0。

    所以int i 是一个暂定定义。 C 编译器会将所有暂定定义组合成一个 i 定义。

    在 C++ 中,由于One Definition Rule(第 3.2/1 节 ISO C++),您的代码格式错误

    任何翻译单元不得包含多个变量的定义、函数、类类型、枚举类型或模板。


    // 但是如果我再次写 int i = 5; 我也会在 C 中得到错误

    因为在这种情况下,由于初始化程序 (5),它不再是一个暂定定义。


    仅供参考

    J.5.11 多个外部定义

    一个对象的标识符可能有多个外部定义,无论是否显式使用关键字 extern;如果定义不一致,或者不止一个被初始化,则行为未定义 (6.9.2)。

    还可以查看excellent post on external variables

    【讨论】:

    • @PrasoonSaurav:这在 C 和 C++ 中都是非法的,但 C 编译器实现了 C 扩展以使其工作。 See this 回答。
    • @legends2k:这在 C 中并不违法。这就是答案的意思“你可以在一个单个翻译单元中有多个暂定定义,但效果与有一个非暂定的外部定义(例如 int a = 0;)。”
    • @PrasoonSaurav:这是未定义的行为;你检查comment by litb了吗?
    • @legends2k :不,不是因为在这种情况下链接不存在分歧。
    【解决方案2】:

    要更好地理解暂定定义,请转至this

    【讨论】:

      【解决方案3】:

      这被称为暂定定义。仅在 C 中允许。

      暂定定义是任何外部的 没有存储的数据声明 类说明符,没有初始化器。 A 暂定定义变为完整 定义如果结束 已到达翻译单元,但没有 定义出现了 标识符的初始化程序。在 这种情况,编译器保留 对象的未初始化空间 已定义。

      以下陈述显示正常定义和暂定定义。

      int i1 = 10;         /* definition, external linkage */
      static int i2 = 20;  /* definition, internal linkage */
      extern int i3 = 30;  /* definition, external linkage */
      int i4;              /* tentative definition, external linkage */
      static int i5;       /* tentative definition, internal linkage */
      
      int i1;              /* valid tentative definition */
      int i2;              /* not legal, linkage disagreement with previous */
      int i3;              /* valid tentative definition */
      int i4;              /* valid tentative definition */
      int i5;              /* not legal, linkage disagreement with previous */
      

      C++ 不支持暂定定义的概念:没有存储类说明符的外部数据声明始终是一个定义。

      从这里:Tentative Definitions

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-20
        • 2011-09-04
        • 2013-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多