gpt4 book ai didi

c++ - 具有不同编译器的不同翻译单元中的内联函数标记未定义的行为?

转载 作者:可可西里 更新时间:2023-11-01 18:38:13 25 4
gpt4 key购买 nike

在 visual studio 中,您可以为各个 cpp 文件设置不同的编译器选项。例如:在“代码生成”下,我们可以在 Debug模式下启用基本的运行时检查。或者我们可以更改浮点模型(精确/严格/快速)。这些只是例子。有很多不同的标志。

一个内联函数可以在程序中定义多次,只要定义相同即可。我们将此功能放入标题中,并将其包含在多个翻译单元中。现在,如果不同 cpp 文件中的不同编译器选项导致函数的编译代码略有不同,会发生什么情况?那么他们确实不同,我们有未定义的行为?您可以将函数设为静态(或将其放入未命名的命名空间),但更进一步,直接在类中定义的每个成员函数都是隐式内联的。这意味着如果这些 cpp 文件共享相同的编译器标志,我们只能在不同的 cpp 文件中包含类。我无法想象这是真的,因为这基本上很容易出错。

我们在未定义行为领域真的那么快吗?还是编译器会处理这种情况?

最佳答案

就标准而言,命令行标志的每种组合都会将编译器转换为不同的实现。虽然实现能够使用由其他实现生成的目标文件很有用,但标准并未强加要求它们这样做。

即使没有内联,也可以考虑在一个编译单元中使用以下函数:

char foo(void) { return 255; }

和下面的另一个:

char foo(void);
int arr[128];
void bar(void)
{
int x=foo();
if (x >= 0 && x < 128)
arr[x]=1;
}

如果 char 在两个编译单元中都是有符号类型,则第二个单元中 x 的值将小于零(从而跳过数组赋值)。如果它在两个单元中都是无符号类型,它将大于 127(同样跳过赋值)。但是,如果一个编译单元使用有符号的 char 而另一个使用无符号的,并且如果实现期望返回值在结果寄存器中进行符号扩展或零扩展,则结果可能是编译器可能会确定 x 不能大于 127,即使它包含 255,或者它不能小于 0,即使它包含 -1。因此,生成的代码可能会访问 arr[255]arr[-1],这可能会带来灾难性的后果。

虽然在许多情况下使用不同的编译器标志组合代码应该是安全的,但标准并未努力区分这种混合是安全的还是不安全的。

关于c++ - 具有不同编译器的不同翻译单元中的内联函数标记未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52050941/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com