假设我有两个文件:
== File1中==
extern char* foo;
==文件2 ==
double foo;
尽管类型不匹配,这两个文件似乎可以编译和链接g ++和clang ++。据我所知,建议的做法是将extern声明放在两个文件都包含的标题中,这样File2就会抛出重定义错误。
我的问题是:
答案 0 :(得分:3)
根据c ++标准,这会导致未定义的行为吗?
嗯,真正的问题是这是未定义的行为还是标准将其指定为格式错误的(标准用语)。因为,显然,这是不正确的。我试图从标准中找到关于此的东西,但无济于事。但是,在许多类似的情况下,例如,decl / def的不匹配或在链接器上抛出时髦的东西(参见第3.5,7.5节,或搜索“extern”或“linkage”),标准通常最终会说:< / p>
该计划格式错误,无需诊断。
所以,我敢打赌,假设这也是这种情况,这是非常安全的。这意味着这是错误的代码,比“未定义的行为”更糟糕,因为UB通常会对特定的实现有某种合理的行为(尽管你不应该推测这种行为会是什么,当然也不会依赖于炒)。标准中使用了“格式错误”这个术语,你可以或多或少地推断它意味着代码是FUBAR。这也意味着标准不要求链接器以允许它捕获这种错误的方式实现,这就是它正确编译和链接的原因,但是当你运行它时坚持你的袜子
联系人能否抓住这种类型的不匹配?
理论上,是的。链接器实现可以将变量的类型(使用名称修改)编码到其外部符号中,从而能够限制与类型匹配的事物的链接(例如,像重载函数),或者在发生诊断(错误)时它遇到类型不匹配。我认为与标准相比,前者过于宽松。
但是,我所知道的所有编译器都不会破坏变量的名称,因此,您可以假设这种不匹配是“格式错误,无需诊断”。
答案 1 :(得分:2)
是的,绝对是的。根据c ++标准,这会导致未定义的行为吗?
如果不是File1中foo的内容?
嗯,它的值为零,因为double foo;
未设置为任何值。但是因为你不能依赖零值实际上与指针的NULL相同,所以如果你试图以某种方式将foo
作为指针与foo
进行比较,则无法说明会发生什么一双。
当然,如果指定了指针foo
,例如foo = malloc(100);
,然后double foo
将包含指针的位,这很可能不是一个特别好的浮点数 - 很可能是64位系统上的非法指针,如前几位很可能是零,这往往意味着该值为零,在这种情况下,其余的位也应该为零。虽然,它确实取决于浮点的内部格式,以及指针的实际值
联系人能否抓住这种类型的不匹配?
不,即使在C ++中,变量的名称也不会被“修改”。只有函数具有编码到函数名称中的函数类型。
从技术上讲,链接器或某些编译器组件可以跟踪符号所代表的类型,然后给出错误或警告。但是标准没有要求这样做。你需要做正确的事。