这主要是对Should definition and declaration match?
的跟进在C中合法(例如)int a[10];
在一个编译单元中,而extern int a[4];
在另一个编译单元中是否合法?
(您可以在my answer中找到一个工作示例来回答问题)
免责声明:
即使引用帖子中的不同评论发现作为UB,我也找不到任何权威参考。所以我会说这里没有UB,第二个编译单元可以访问数组的开头,但我真的想要一个确认 - 或者说是为什么它是UB的参考
答案 0 :(得分:6)
这是未定义的行为。
C99第6.2.7.2节规定:
引用同一对象或函数的所有声明都应具有 兼容型;否则,行为未定义。
注意:正如下面的评论中所提到的,这里的重要部分是 [...]引用相同的对象[...] ,这是在6.2.2进一步定义:
在构成一个翻译单元和库的集合中 整个程序,每个特定标识符的声明 外部链接表示相同的对象或功能。
关于数组类型的类型兼容性规则,C99的第6.7.5.2.4节阐明了两种数组类型兼容的含义:
要兼容两种阵列类型,两者都应兼容 元素类型,如果两个大小说明符都存在,并且是 整数常量表达式,然后两个大小说明符都应该具有 相同的常数值。如果在上下文中使用这两种数组类型 这要求它们兼容,如果是,则是未定义的行为 两个大小说明符评估为不相等的值。
(强调我的)
在现实世界中,只要您坚持使用1D数组,它就可能是无害的,因为没有边界检查,并且无论大小说明符如何,第一个元素的地址都保持不变,但请注意{{ 1}}运算符将在每个源文件中返回不同的值(为编写错误代码打开了一个绝佳的机会)。
如果您决定对此示例进行推断并声明具有不同尺寸大小的多维数组,事情开始变得非常难看,因为数组中每个元素的偏移量将不再与实际尺寸匹配。
答案 1 :(得分:-1)
是的,这是合法的。语言允许它。
在您的特定情况下,没有未定义的行为,因为extern
声明的数组小于实际分配的数组。
它可以用于声明模块使用“未发布的”数组元素的情况。算法的内务管理(抽象隐藏)。