c - 在不同的编译单元中以不同的大小声明与 extern 相同的数组是否是 UB

标签 c linker language-lawyer

这主要是对 Should definition and declaration match? 的跟进

问题

在 C 中,在一个编译单元中有(例如)int a[10]; 和在另一个编译单元中有 extern int a[4]; 是否合法?

(您可以在 my answer 中找到一个工作示例来引用问题)


免责声明:

  • 我知道这很危险,不会在生产代码中这样做
  • 我知道如果你在同一个编译单元中有两个(通常通过在包含定义的文件中包含一个 .h)编译器检测到一个错误
  • 我已经阅读了 Jonathan Leffler 的优秀作品 answerHow do I use extern to share variables between source files?但在那里找不到这个特定点的答案——即使乔纳森表现出更糟糕的用法……

即使引用帖子中的不同评论发现它是 UB,我也找不到任何权威引用。所以我会说这里没有 UB,第二个编译单元可以访问数组的开头,但我真的想要一个确认 - 或者一个关于为什么它是 UB 的引用

最佳答案

这是未定义的行为。

C99 第 6.2.7.2 节指出:

All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.

注意:正如下面评论中提到的,这里的重要部分是[...] 指的是同一个对象[...],即6.2.2进一步定义:

In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function.

关于数组类型的类型兼容性规则,C99的6.7.5.2.4节明确了两种数组类型兼容的含义:

For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.

(强调我的)

在现实世界中,只要你坚持一维数组,它可能是无害的,因为没有边界检查,第一个元素的地址保持不变,无论大小说明符如何,但请注意 sizeof 运算符将在每个源文件中返回不同的值(为编写错误代码打开了一个绝妙的机会)。

如果您决定对此示例进行推断并声明具有不同维度大小的多维数组,事情就会开始变得非常糟糕,因为数组中每个元素的偏移量将不再与实际维度匹配。

关于c - 在不同的编译单元中以不同的大小声明与 extern 相同的数组是否是 UB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31476480/

相关文章:

C - 如何获取 Char 中的 4 个最低有效位

c - 我应该重置 SIGINT/SIGTERM 上的 termios 设置吗?

c - 删除 C 程序中的条件以加快速度

linker - CMake : FIND_LIBRARY problem

c++ - 在 C++17 中修改 constexpr 函数中的全局变量

python - 有关为Vexed关卡编写解算器的建议

C++ 链接问题,好像我不能链接到标准 C++ 东西

c++ - 我不知道这是什么(C++ 链接器错误)

c++ - 可以空引用吗?

c++ - [lex.ccon] 中 c-char 的定义可能存在矛盾