声明和定义之间的冲突是否会导致未定义的行为?

时间:2018-11-27 04:16:23

标签: c++ c language-lawyer undefined-behavior

例如,在一个源文件中:

extern int a[10];
int main()
{
   (void)sizeof(a);
   return 0;
}

在第二个源文件中,我们有:

int a[20];//different with the first source 

上面的代码是否会导致不确定的行为?据我所知,在 C 中它说:

  

所有引用相同对象或函数的声明应具有 compatible 类型;否则,行为是不确定的。

int[10]int[20]是否兼容(在c看来)?那么 C ++ 标准呢?

此外,如果没有第二个源文件,则使用sizeof(a)a仅具有声明)是否合法?

2 个答案:

答案 0 :(得分:10)

是的,这是C语言中未定义的行为,它们不兼容,请参见C11 6.7.6.2 Array declarators paragraph 6

  

要使两个数组类型兼容,两个数组必须兼容   元素类型,以及是否同时存在两个大小说明符   整数常量表达式,则两个大小说明符都应具有   相同的常数值。如果在上下文中使用了两种数组类型   要求它们兼容,如果   两个大小说明符的值不相等。

[basic.link]p11中C ++不需要格式错误的诊断:

  

在对类型进行所有调整之后(在其typedef被其定义替换之前),所有引用给定变量或函数的声明所指定的类型应相同,不同之处在于数组对象的声明可以指定不同的数组类型。是否存在主数组绑定([dcl.array])。   违反此类型身份规则无需诊断。

答案 1 :(得分:1)

某些实现将根据平台的一组约定定义的规则来处理导入和导出的符号,这些规则通常在文档中描述,在现代术语中,该文档称为“应用程序二进制接口”。如果一个模块(编译单元)导出一个符号,另一个模块导入它,则每个定义及其相互作用都将按照ABI的描述进行,而与导入或导出符号的代码语言规则无关。

其他实现,尤其是那些使用整体程序优化的实现,可能会处理从一个C编译单元导出并由另一C编译单元使用的符号,其方式与ABI所建议的方式不同,特别是如果这样做可以使事情更高效,或允许构建系统进行更好的诊断。

由于这两种方法都有实质性的优点和缺点,因此该标准对于实现如何处理不同模块中的功能之间的交互作用一无所知。如果平台ABI恰好定义了一个行为,一个C实现文档记录了C模块以ABI定义的方式进行交互,则无论该标准是否提出任何要求,都将在该实现上定义行为。在标准不施加任何要求的其他情况下,可能发生任何事情。