GCC size_t和大小算术转换为 int
gcc size_t and sizeof arithmetic conversion to int
我决定测试编译一个启用了 -Wsign-conversion 的项目,看看会出现什么警告,并遇到了一些似乎不对劲的东西,其中 gcc 的行为与 clang 不同。有人可以告诉我哪个是正确的吗?
我有一个接受size_t
参数的函数:
void func(size_t) {}
其他一些结构
struct Test {};
和呼叫代码
int i = some_initialiser();
func(sizeof(Test) + static_cast<size_t>(i));
所以根据我的理解,sizeof
返回size_t
,而两个类型为size_t
的变量之间的算术应该返回一个size_t
,所以这里不应该有任何转换除了我的static_cast
,但 gcc 给了我警告
warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
Clang 在这里没有警告,但如果我按预期删除函数调用中的static_cast
,则会发出警告。
这是 gcc 中的一个已知错误,在版本 9.3.0 及更高版本中修复。
警告是有效的(编译器可以警告他们喜欢的任何内容(,但 gcc 的行为与其自己的文档相矛盾。此问题有一个现有的错误报告(见下文(。
下面是一个更简单的测试用例来说明这个问题:
#include <cstddef>
int main() {
int i = 42;
size_t s0 = sizeof (int) + (size_t)i;
size_t s1 = sizeof (int) + static_cast<size_t>(i);
}
当我使用 gcc 9.1.0 在我的系统上编译它时,我得到:
$ g++ -Wsign-conversion -c c.cpp
c.cpp: In function ‘int main()’:
c.cpp:4:32: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
4 | size_t s0 = sizeof (int) + (size_t)i;
| ^~~~~~~~~
c.cpp:5:32: warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
5 | size_t s1 = sizeof (int) + static_cast<size_t>(i);
| ^~~~~~~~~~~~~~~~~~~~~~
$
请注意,C 样式转换和static_cast
都会出现警告。
确实,转换可能会改变结果的符号(将负int
转换为size_t
产生正结果(,但 gcc 的-Wsign-conversion
文档说:
'-Wsign-conversion'
Warn for implicit conversions that may change the sign of an
integer value, like assigning a signed integer expression to an
unsigned integer variable. An explicit cast silences the warning.
In C, this option is enabled also by '-Wconversion'.
在这种情况下,显式强制转换不会使警告静音。
此错误已被报告:
Bug 87519 - -Wsign-conversion 显式强制转换无法静音警告
修复程序是在 gcc git 存储库中提交61e52125c935279af11b10d27060a96bff7477a4
,提交于 2019-08-08。
警告是正确的。
如果i
具有负值,则转换将有问题。你的函数应该返回一个无符号值(例如无符号的整数(。
来自 GCC 文档 - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:
对于C++,还要警告用户定义的转换的重载解析混淆;以及从不使用类型转换运算符的转换:转换为
void
、相同类型、基类或对它们的引用。默认情况下,有关有符号整数和无符号整数之间转换的警告在 C++ 中处于禁用状态,除非显式启用-Wsign-conversion
。
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 是否可以从int转换为enum类类型
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 功能样式转换从 'int' 到 'ItemType' 的匹配转换
- 将 int 数组转换为 std::vector<int*>
- 如何转换 int 变量并附加到常量 wchar_t*
- 类型转换<int>的舍入问题
- 在Objective-C中调用sqlite3数据库时,如何调用和转换int/NSNumber
- 转换 int -> 无符号长 长 是否由标准定义
- 简单的 int 到字符串转换..int to const char* 无效
- 如何将转换 int 除法键入为浮点数
- C++类型转换 int * 到类
- 预期的类型说明符,并且无法在初始化时转换“int*”
- 转换int并将其与char*连接
- 字符串流在转换int型时添加新行
- 转换int为字符串/char c++ /Arduino
- c# P-Invoke:如何转换INT fun(BYTE *bStream, UINT16 *nCount, const
- 类型转换(int**)和int(*)的区别
- 从"int"到"nodeType"的无效转换<int>
- 从无符号int构造对强制转换int的引用