3

假设我有两个文件:

==文件1==

extern char* foo;

==文件2==

double foo;

尽管类型不匹配,这两个文件似乎与 g++ 和 clang++ 都可以很好地编译和链接。据我了解,推荐的做法是将 extern 声明放在两个文件都包含的标头中,因此 File2 将引发重新定义错误。

我的问题是:

  • 根据 c++ 标准,这是否会导致未定义的行为?如果不是 File1 中的foo中的内容是什么?
  • 链接器能捕捉到这种类型不匹配吗?
4

2 回答 2

3

根据 c++ 标准,这是否会导致未定义的行为?

好吧,真正的问题是这是否是未定义的行为,或者它是否被标准指定为格式错误用标准术语)。因为,显然,这是不正确的。我试图从标准中找到一些关于此的内容,但无济于事。然而,在许多类似的情况下,例如 decl/def 不匹配或在链接器上抛出一些奇怪的东西(参见第 3.5、7.5 节,或搜索“extern”或“linkage”),标准通常会说:

该程序格式错误,无需诊断。

所以,我敢打赌,假设这里也是这种情况是非常安全的。这意味着这是错误的代码,比“未定义的行为”更糟糕,因为 UB 通常会对特定的实现有某种合理的行为(尽管你不应该推测这种行为会是什么,当然也不应该依赖它推测)。“格式错误”一词在标准中使用得非常随意,您可以或多或少地推断出它意味着代码是 FUBAR。这也意味着根据标准,链接器不需要以允许它捕获此类错误的方式实现,这就是它正确编译和链接的原因,但在你运行它时请抓住你的袜子.

链接器能捕捉到这种类型不匹配吗?

理论上,是的。链接器实现可以将变量的类型编码(使用名称修饰)到其外部符号中,因此能够限制与类型匹配的事物的链接(例如,重载函数),或者在发生时抛出诊断(错误)它遇到类型不匹配。我认为与标准相比,前者过于宽松。

但是,我所知道的所有编译器都不会破坏变量的名称,因此,您可以假设这种不匹配是“格式错误的,不需要诊断”。

于 2013-02-05T00:28:41.373 回答
2

根据 c++ 标准,这是否会导致未定义的行为?

当然是。

如果不是 File1 中的 foo 中的内容是什么?

嗯,它的值为零,因为double foo;没有设置任何东西。foo但是,由于您不能依赖双精度值的零值实际上与指针的 N​​ULL 相同,因此如果您尝试以某种方式将指针与双精度值进行比较,则不知道会发生什么foo

自然,如果指针foo被分配,例如foo = malloc(100);,那么 doublefoo将包含指针的位,这很可能不是一个特别好的浮点数 - 在 64 位系统上很可能是非法的,因为前几位将最可能为零,这往往意味着该值为零,在这种情况下,其余位也应为零。虽然,它确实取决于浮点的内部格式,以及指针的实际值

链接器能捕捉到这种类型不匹配吗?

不,即使在 C++ 中,变量的名称也不会因类型而“损坏”。只有函数具有编码到函数名称中的函数类型。

从技术上讲,链接器或某些编译器组件可以跟踪符号表示的类型,然后给出错误或警告。但是标准没有要求这样做。你需要做正确的事。

于 2013-02-05T00:01:51.260 回答