简体   繁体   English

gcc size_t 和 sizeof 算术转换为 int

[英]gcc size_t and sizeof arithmetic conversion to int

I decided to test compile a project with -Wsign-conversion enabled, to see what warnings would come up, and came across something that doesn't seem right, where gcc behaves differently than clang.我决定在启用 -Wsign-conversion 的情况下测试编译一个项目,看看会出现什么警告,并遇到一些似乎不正确的东西,其中 gcc 的行为与 clang 不同。 Can someone please tell me which is correct?有人可以告诉我哪个是正确的吗?

I have a function that takes a size_t param:我有一个接受size_t参数的函数:

void func(size_t) {}

some other struct其他一些结构

struct Test {};

and calling code和调用代码

int i = some_initialiser();
func(sizeof(Test) + static_cast<size_t>(i));

So from my understanding, sizeof returns size_t , and arithmetic between two variables of type size_t should return a size_t , so there shouldn't be any conversion here other than my static_cast , but gcc gives me the warning因此,从我的理解, 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 doesn't warn here, but does warn if I remove the static_cast in the function call, as expected. Clang 不会在这里发出警告,但如果我按预期删除函数调用中的static_cast ,则会发出警告。

This is a known bug in gcc, fixed in versions 9.3.0 and above.这是 gcc 中的一个已知错误,已在 9.3.0 及更高版本中修复。

The warning is valid (compilers can warn about anything they like), but gcc's behavior contradicts its own documentation.警告是有效的(编译器可以警告任何他们喜欢的东西),但 gcc 的行为与其自己的文档相矛盾。 There is an existing bug report for this problem (see below).这个问题有一个现有的错误报告(见下文)。

Here's a simpler test case that illustrates the issue:这是一个更简单的测试用例,说明了这个问题:

#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);
}

When I compile it on my system using gcc 9.1.0, I get:当我使用 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);
      |                                ^~~~~~~~~~~~~~~~~~~~~~
$ 

Note that the warning occurs both for a C-style cast and for a static_cast .请注意,C 样式转换和static_cast都会出现警告。

It's true that the conversion may change the sign of the result (converting a negative int to size_t yields a positive result), but gcc's documentation for -Wsign-conversion says:确实,转换可能会改变结果的符号(将负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'.

In this case, an explicit cast is not silencing the warning.在这种情况下,显式强制转换不会使警告静音。

This bug had already been reported:这个错误已经被报告了:
Bug 87519 - -Wsign-conversion -Wconversion explicit cast fails to silence warning错误 87519 - -Wsign-conversion -Wconversion 显式转换无法使警告静音

The fix is commit 61e52125c935279af11b10d27060a96bff7477a4 in the gcc git repo, committed 2019-08-08.修复是在 gcc git repo 中提交61e52125c935279af11b10d27060a96bff7477a461e52125c935279af11b10d27060a96bff7477a4年 8 月 8 日提交。

The warning is correct.警告是正确的。

If i has a negative value the casting will be problematic.如果i有一个负值,铸造就会有问题。 Your function should return an unsigned value (eg unsigned int).您的函数应该返回一个无符号值(例如 unsigned int)。

From GCC documentation - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html :来自 GCC 文档 - https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

For C++, also warn for confusing overload resolution for user-defined conversions;对于 C++,还警告混淆用户定义转换的重载解析; and conversions that never use a type conversion operator: conversions to void , the same type, a base class or a reference to them.和从不使用类型转换运算符的转换:转换为void 、相同类型、基类或对它们的引用。 Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.除非显式启用-Wsign-conversion否则 C++ 中默认禁用有关有符号和无符号整数之间转换的警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM