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;
}
Clang 在使用-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
查看在 godbolt 上的两个编译器上运行的程序。
强制转换不会在编译的代码中发生,val2
保留其原始值。计算结果是正确的。这个警告警告我的实际危险是什么?如何触发此行为?警告是假的吗?
第二次转换是事情变得依赖于实现的地方。
第一个(表达式val1+val2
的评估(触发val2
从有符号到无符号的转换,这是符合标准和记录的。因此,表达式的结果是无符号的。
第二个(将生成的未签名转换回已签名(是潜在问题随之而来的地方。如果无符号值不在目标有符号类型的定义域中(在本例中,它不在(,则会出现实现行为,您不能假设该行为在已知域中可移植。
这个警告警告我的实际危险是什么?
潜在的危险是您可能没有意识到隐式符号转换,并且是偶然进行的。如果它是故意的并且按照预期行事,那么就没有危险(。
如何触发此行为?
您已触发隐式符号转换。
也就是说,如果您想看到一些可能让您感到惊讶的输出,请尝试以下操作:
std::cout << val1 + val2;
警告是假的吗?
取决于你对假货的定义。
程序中肯定存在隐式符号转换,因此,如果您要求编译器警告隐式符号转换,那么编译器警告程序中的隐式符号转换是完全正确的。
默认情况下不启用此警告选项,在使用 -Wall 启用"所有"警告时,甚至在使用 -Wextra 启用"额外"警告时,都是有原因的。这些符号转换警告具有明确定义行为的程序,但对于没有密切关注的人来说,这可能会令人惊讶。尽管有此警告,程序也可能有意义且正确。
- 我的代码输出总是得到 0
- 代码输出随机符号,我不确定出了什么问题
- 为什么当我正确执行语法时,我的代码输出为 0
- 为什么这段代码输出这么多数字
- 当我输入任何内容时,我的代码输出无效
- 我在让我的代码输出整个链表时遇到问题.它只是输出我修改过的一些文本文件,而不是整个东西
- 在 netbeans 中将C++代码输出为汇编语言
- 使用向量(STL)时,未定义的行为,请说明理性背后的以下代码输出
- 当我尝试运行此代码输出时"merge.exe has stopped working"?
- 欧拉项目 #14 代码输出未到来
- C++中的代码输出出现问题
- 如何删除此代码输出的结束空格
- 这段代码输出什么笑脸
- Win32 键转换代码输出不需要的按键
- 在 QT 中将代码输出到主窗口
- 我无法让此代码输出平均工资率,任何人都可以解释原因
- C++字母等效数字代码输出程序
- 我的代码输出重复
- c++代码输出说明
- C++代码输出负值