【发布时间】:2016-04-21 10:05:17
【问题描述】:
我在回答一个问题时发现了一些奇怪的东西。有问题的代码更复杂,但观察归结为在 MSVC 14.0 中编译的事实:
#include <stdio.h>
void foo(int);
int main()
{
foo(66);
getchar();
}
void foo(const char* str, int x)
{
printf("%s %d\n", str, x);
}
这段代码会产生未定义的行为,因为foo 中str 的值是66,它不指向有效的以空值结尾的字符串,因此在实践中我们(很可能)会遇到段错误。
如前所述,我使用 Visual Studio 2015 - MSVC 14.0 - 来编译它。我正在编译为 C 的代码。如果我们尝试GCC 5.1,它会失败。
起初,我认为这是 C 在早期允许的奇怪事情之一,并且被留在其中以不破坏旧代码(例如隐式函数原型)。但是在这里,我们有一个原型和一个同名的定义,但它们不兼容。为什么编译器不拒绝这个? C 不允许函数重载,所以两个同名的标识符不应该是合法的。
为什么 MSVC 不拒绝此代码?这种行为有解释吗?这在其中一项标准中是否明确允许?
编辑:因为在 cmets 中似乎有很多混乱,我想澄清一下。我知道如何避免此类错误,我总是以最高警告级别编译,并将警告视为错误;这不是重点。这个问题纯粹是理论上的:我想知道这种行为是否合法并在 C 标准中定义。因为两个 C 编译器在给定相同的代码时行为不同,所以有问题。
【问题讨论】:
-
我认为有一个警告......甚至如你所说的 GCC 错误
-
@EugeneSh。很多,但这不会改变任何事情。无效的代码应该被拒绝。
-
好吧,如果您看到编译器之间的区别 - 它是特定于实现的..
-
@EugeneSh。如果您建议接受非法代码是我们可以称之为“特定于实现”的东西,那么我不得不不同意。当然,除非其中一个标准明确允许这种行为,但无论如何,其中一个编译器做错了。
-
MSVC 的行为可能不太可取,但没关系,因为它会生成诊断消息。 C 标准不知道错误和警告。我们也可能无法告诉您为什么 MSVC 开发人员将其设为警告而不是错误。
标签: c visual-c++ function-prototypes