【问题标题】:Does the confliction between declaration and definition cause undefined behavior?声明和定义之间的冲突是否会导致未定义的行为?
【发布时间】:2018-11-27 04:16:22
【问题描述】:

例如,在一个源文件中:

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

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

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

上面的代码会导致未定义的行为吗?据我所知,在 C 它说:

引用同一对象或函数的所有声明都应具有兼容类型;否则,行为未定义。

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

另外,如果没有第二个源文件,使用sizeof(a)是否合法(a只有一个声明)?

【问题讨论】:

  • 1.是的,它确实会导致 UB 2。是的,它是合法的。
  • @n.m.标准是否涵盖过这种情况?我找不到那个。
  • 你问的是 2 种语言,所以这就像 3 个问题合而为一
  • @AnttiHaapala 我相信这是一个有效的问题,OP 对它在 C 中所说的内容有一些概念,并且想知道它是否是未定义的行为,并且还想了解它是否适​​用于 C++。措辞可能会更好。
  • @ShafikYaghmour 不好的先例。当前的标签 wiki 说:“一个问题应该用 c 和 c++ 标记,如果它是关于:* C 和 C++ 之间的特定差异”。这是问题 3。问题 1 和问题 2 是 C++ 和 C 问题,这些定义是否兼容。

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


【解决方案1】:

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

对于要兼容的两种数组类型,两者都应兼容 元素类型,并且如果两个大小说明符都存在,并且是 整数常量表达式,则两个大小说明符都应具有 相同的常数值。如果在上下文中使用这两种数组类型 这要求它们兼容,如果 两个大小说明符的计算结果不相等。

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

在所有类型调整之后(在此期间 typedef 被其定义替换),引用给定变量或函数的所有声明指定的类型应相同,但数组对象的声明可以指定不同的数组类型是否存在主要数组绑定 ([dcl.array])。 在类型标识上违反此规则不需要诊断。

【讨论】:

    【解决方案2】:

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

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

    由于这两种方法都有很大的优点和缺点,因此标准对于实现如何处理不同模块中函数之间的交互是不可知的。如果一个平台 ABI 碰巧定义了一个行为,一个 C 实现记录了 C 模块以 ABI 定义的方式交互,那么无论标准是否强加任何要求,都将在该实现上定义行为.在标准没有强加要求的其他情况下,任何事情都可能发生。

    【讨论】:

      猜你喜欢
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-04
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多