gpt4 book ai didi

c - 在公共(public) block 中有全局变量是一种未定义的行为吗?

转载 作者:行者123 更新时间:2023-12-03 22:59:04 24 4
gpt4 key购买 nike

0.c

int i = 5;

int main(){
return i;
}
1.c
int i;
上面用 gcc 0.c 1.c 编译得很好没有关于 multiple definitions 的任何链接错误.原因是 i生成为 common blocks (-fcommon which is the default behaviour in gcc) .
正确的方法是使用 extern这里缺少的关键字。
我一直在网上搜索这是否是未定义的行为,有些帖子说是,有些人说不是,这非常令人困惑:
是UB
Is having multiple tentative definitions in separate files undefined behaviour?
Why can I define a variable twice in C?
How do I use extern to share variables between source files?
http://port70.net/~nsz/c/c11/n1570.html#J.2

An identifier with external linkage is used, but in the program there does not exist exactly one external definition for the identifier, or the identifier is not used and there exist multiple external definitions for the identifier (6.9).


它不是 UB
Global variables and the .data section
Defining an extern variable in multiple files in C
Does C have One Definition Rule like C++? Look for -fno-common :
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Code-Gen-Options.html
那么是哪一个呢?正在使用 -fcommon为数不多的拥有 multiple definition 的地方之一是允许的,编译器会为你整理出来吗?还是仍然是UB?

最佳答案

根据 C 标准分析代码
最新 C 标准的第 6.9/5 节对此进行了介绍:

Semantics

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for theidentifier; otherwise, there shall be no more than one.


术语“外部定义”不应与“外部链接”或 extern 混淆。关键字,这些是完全不同的概念,恰好有相似的拼写。
“外部定义”是指非试验性的、不在函数内部的定义。
关于暂定定义,这在 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.


所以在你的文件 1.c ,根据 6.9.2/2,行为就像它所说的 int i = 0;反而。这将是一个外部定义。这意味着 0.c1.c两者都表现得好像它们具有违反规则 6.9/5 的外部定义,即不得有超过一个外部定义。
违反语义规则意味着 行为未定义,无需诊断。
解释“未定义的行为”是什么意思
另见: Undefined, unspecified and implementation-defined behavior
如果不清楚,C 标准说“行为未定义”意味着 C 标准没有定义行为。基于不同的符合实现的相同代码(或在相同符合实现的基础上重新构建)可能表现不同,包括拒绝程序、接受程序或您可能想象的任何其他结果。
(注意 - 某些程序的行为的定义性取决于运行时条件;这些程序不能在编译时被拒绝,并且必须按照指定的方式运行,除非出现导致行为未定义的条件。但这并不适用到这个问题中的程序,因为所有可能的执行都会遇到违反 6.9/5)。
对于 C 标准未定义行为的情况,编译器供应商可能会或可能不会提供稳定和/或记录的行为。
对于您问题中的代码,编译器供应商提供可靠的行为是很常见的(哈哈);这记录在标准的非规范性附录 J.5.11 中:

J.5 Common extensions

J.5.11 Multiple external definitions1 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).


如果 -fcommon,gcc 编译器似乎实现了这个扩展。提供了开关,如果 -fno-common 则禁用它已提供(默认设置可能因编译器版本而异)。

脚注:我故意避免使用与 C 标准未定义的行为有关的“定义”一词,因为在我看来,这是 OP 混淆的原因之一。

关于c - 在公共(public) block 中有全局变量是一种未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67587124/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com