gcc size_t 和 sizeof 算术转换为 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
returns size_t
,size_t
类型的两个变量之间的算术应该 return a 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
,则会发出警告。
警告是正确的。
如果 i
为负值,则转换会出现问题。您的函数应该 return 一个无符号值(例如 unsigned int)。
来自 GCC 文档 - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:
For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to void
, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion
is explicitly enabled.
这是 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 -Wconversion explicit cast fails to silence warning
修复是 gcc git 存储库中的提交 61e52125c935279af11b10d27060a96bff7477a4
,提交于 2019-08-08。
我决定在启用 -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
returns size_t
,size_t
类型的两个变量之间的算术应该 return a 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
,则会发出警告。
警告是正确的。
如果 i
为负值,则转换会出现问题。您的函数应该 return 一个无符号值(例如 unsigned int)。
来自 GCC 文档 - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:
For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to
void
, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless-Wsign-conversion
is explicitly enabled.
这是 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 -Wconversion explicit cast fails to silence warning
修复是 gcc git 存储库中的提交 61e52125c935279af11b10d27060a96bff7477a4
,提交于 2019-08-08。