Clang 向我发出签名更改的警告,但代码仍会产生正确的输出
Clang gives me a warning of signedness change, however the code still produces correct output
我正在分析代码库中的一些警告,对 Clang 生成的警告感到困惑
考虑以下 C++ 代码:
#include <iostream>
int main(int , char *[])
{
uint32_t val1 = 10;
int32_t val2 = -20;
int32_t result = val1 + val2;
std::cout << "Result is " << result << "\n";
return 0;
}
使用 -Wconversion
编译这段代码时,Clang 给出了以下警告
<source>:9:25: warning: implicit conversion changes signedness:
'unsigned int' to 'int32_t' (aka 'int') [-Wsign-conversion]
int32_t result = val1 + val2;
~~~~~~ ~~~~~^~~~~~
<source>:9:27: warning: implicit conversion changes signedness:
'int32_t' (aka 'int') to 'unsigned int' [-Wsign-conversion]
int32_t result = val1 + val2;
~ ^~~~
2 warnings generated.
GCC 也给了我这个警告,但是我需要提供 -Wsign-conversion
来触发它。
警告说 val2
将转换为 unsigned int
,因此会失去它的标志。到目前为止,一切都很好。然而,我期望上面的代码会产生 不正确的 输出,令我惊讶的是它工作得很好。
Result is -10
在两个编译器 on godbolt 上查看程序 运行。
编译后的代码中不会发生强制转换,val2
保留其原始值。计算结果正确。此警告警告我注意的 实际 危险是什么?我怎样才能触发这种行为?警告是假的吗?
second 转换是实现依赖的地方。
第一个(表达式 val1+val2
的计算)触发从 val2
到无符号从有符号的转换,这是符合标准和记录的。因此表达式的结果是无符号的。
第二个(将生成的无符号 返回 转换为有符号)是潜在问题随之而来的地方。如果无符号值不在目标有符号类型的定义域内(在本例中,它不在),则会出现实现行为,您不能假设它在已知的宇宙中是可移植的。
What is the actual danger that this warning is warning me against?
潜在的危险是您可能没有意识到隐式符号转换,而无意中进行了转换。如果它是故意的并且表现得如所愿,那么就没有危险。
How can I trigger this behaviour?
您已经触发了隐式符号转换。
就是说,如果您想看到一些可能会让您感到惊讶的输出,请试试这个:
std::cout << val1 + val2;
Is the warning bogus?
取决于你对假冒的定义。
程序中肯定存在隐式符号转换,因此如果您要求编译器警告隐式符号转换,那么编译器警告程序中的隐式符号转换是完全正确的.
默认情况下不启用此警告选项是有原因的,在使用 -Wall 启用 "all" 警告时,甚至在使用 -Wextra 启用 "extra" 警告时也是如此。这些符号转换警告警告程序具有明确的行为,但对于没有密切注意的人来说可能会感到惊讶。尽管有此警告,程序仍然有意义且正确。
我正在分析代码库中的一些警告,对 Clang 生成的警告感到困惑
考虑以下 C++ 代码:
#include <iostream>
int main(int , char *[])
{
uint32_t val1 = 10;
int32_t val2 = -20;
int32_t result = val1 + val2;
std::cout << "Result is " << result << "\n";
return 0;
}
使用 -Wconversion
<source>:9:25: warning: implicit conversion changes signedness:
'unsigned int' to 'int32_t' (aka 'int') [-Wsign-conversion]
int32_t result = val1 + val2;
~~~~~~ ~~~~~^~~~~~
<source>:9:27: warning: implicit conversion changes signedness:
'int32_t' (aka 'int') to 'unsigned int' [-Wsign-conversion]
int32_t result = val1 + val2;
~ ^~~~
2 warnings generated.
GCC 也给了我这个警告,但是我需要提供 -Wsign-conversion
来触发它。
警告说 val2
将转换为 unsigned int
,因此会失去它的标志。到目前为止,一切都很好。然而,我期望上面的代码会产生 不正确的 输出,令我惊讶的是它工作得很好。
Result is -10
在两个编译器 on godbolt 上查看程序 运行。
编译后的代码中不会发生强制转换,val2
保留其原始值。计算结果正确。此警告警告我注意的 实际 危险是什么?我怎样才能触发这种行为?警告是假的吗?
second 转换是实现依赖的地方。
第一个(表达式 val1+val2
的计算)触发从 val2
到无符号从有符号的转换,这是符合标准和记录的。因此表达式的结果是无符号的。
第二个(将生成的无符号 返回 转换为有符号)是潜在问题随之而来的地方。如果无符号值不在目标有符号类型的定义域内(在本例中,它不在),则会出现实现行为,您不能假设它在已知的宇宙中是可移植的。
What is the actual danger that this warning is warning me against?
潜在的危险是您可能没有意识到隐式符号转换,而无意中进行了转换。如果它是故意的并且表现得如所愿,那么就没有危险。
How can I trigger this behaviour?
您已经触发了隐式符号转换。
就是说,如果您想看到一些可能会让您感到惊讶的输出,请试试这个:
std::cout << val1 + val2;
Is the warning bogus?
取决于你对假冒的定义。
程序中肯定存在隐式符号转换,因此如果您要求编译器警告隐式符号转换,那么编译器警告程序中的隐式符号转换是完全正确的.
默认情况下不启用此警告选项是有原因的,在使用 -Wall 启用 "all" 警告时,甚至在使用 -Wextra 启用 "extra" 警告时也是如此。这些符号转换警告警告程序具有明确的行为,但对于没有密切注意的人来说可能会感到惊讶。尽管有此警告,程序仍然有意义且正确。