C 中允许重定义,但 C++ 中不允许?

发布于 2024-10-24 03:14:57 字数 166 浏览 6 评论 0原文

为什么这段代码在 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
}

Why does this code work in C but not in C++?

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

int main(){

  // using i
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

葵雨 2024-10-31 03:14:57

C 中允许临时定义,但 C++ 中不允许。

临时定义是任何没有存储类说明符且没有存储类说明符的外部数据声明。初始化程序。

C99 6.9.2/2

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

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

在 C++ 中,由于 单一定义规则,您的代码格式不正确(第 3.2/1 ISO C++ 节)

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


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

因为在这种情况下,由于初始值设定项 (5),它不再保留为暂定定义。


只是为了提供信息

J.5.11 多个外部定义

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

另请查看这篇关于外部变量的优秀文章

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

A tentative definition is any external data declaration that has no storage class specifier and no initializer.

C99 6.9.2/2

A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.

So int i is a tentative definition. The C compiler will combine all of the tentative definitions into a single definition of i.

In C++ your code is ill-formed due to the One Definition Rule (Section 3.2/1 ISO C++)

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.


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

Because in that case it no longer remains a tentative definition because of the initializer (5).


Just for the sake of information

J.5.11 Multiple external definitions

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

Also check out this excellent post on external variables.

笑,眼淚并存 2024-10-31 03:14:57

Tha 称为暂定定义。仅在 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++ 不支持暂定定义的概念:没有存储类说明符的外部数据声明始终是一个定义。

从此处:暂定定义

Tha is called tentative definition. It's allowed only in C.

A tentative definition is any external
data declaration that has no storage
class specifier and no initializer.
A
tentative definition becomes a full
definition if the end of the
translation unit is reached and no
definition has appeared with an
initializer for the identifier. In
this situation, the compiler reserves
uninitialized space for the object
defined.

The following statements show normal definitions and tentative definitions.

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++ does not support the concept of a tentative definition: an external data declaration without a storage class specifier is always a definition.

From here: Tentative Definitions

帥小哥 2024-10-31 03:14:57

要更好地理解暂定定义,请阅读

To understand tentative definition better, go through this

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文