gcc size_t和sizeof算术转换为int [英] gcc size_t and sizeof arithmetic conversion to int

查看:324
本文介绍了gcc size_t和sizeof算术转换为int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我决定在启用-Wsign-conversion的情况下测试编译项目,以查看会出现什么警告,并且遇到gcc的行为与clang不同的错误消息.有人可以告诉我哪个是正确的吗?

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. Can someone please tell me which is correct?

我有一个采用size_t参数的函数:

I have a function that takes a size_t param:

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给了我警告

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

 warning: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]

Clang在这里没有警告,但是会警告我是否如预期的那样在函数调用中删除了static_cast.

Clang doesn't warn here, but does warn if I remove the static_cast in the function call, as expected.

推荐答案

这是gcc中的已知错误,现已修复,但尚未发布.

This is a known bug in gcc, now fixed but not yet released.

警告是有效的(编译器可以警告他们喜欢的任何东西),但是gcc的行为与它自己的文档相矛盾.有针对此问题的现有错误报告(请参见下文).

The warning is valid (compilers can warn about anything they like), but gcc's behavior contradicts its own documentation. 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);
}

当我使用gcc 9.1.0在系统上编译它时,我得到:

When I compile it on my system using gcc 9.1.0, I get:

$ 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都会发生警告.

Note that the warning occurs both for a C-style cast and for a static_cast.

的确,转换可能会改变结果的符号(将负的int转换为size_t会得到正的结果),但是gcc的-Wsign-conversion文档说:

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:

'-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.

已报告此错误:
错误87519--Wsign-conversion -Wconversion显式强制转换无法使警告静音
我已经添加了测试用例以及指向该问题和错误报告的答案的链接.

This bug has already been reported:
Bug 87519 - -Wsign-conversion -Wconversion explicit cast fails to silence warning
I've added my test case and a link to this question and answer to the bug report.

来自Marek Polacek的新评论报告:

A new comment from Marek Polacek on the bug report:

固定在主干上,稍后将反向移植到9.3.

Fixed on trunk, will backport to 9.3 later.

此修复程序是在2019年8月8日提交的gcc git repo中提交了61e52125c935279af11b10d27060a96bff7477a4.

The fix is commit 61e52125c935279af11b10d27060a96bff7477a4 in the gcc git repo, committed 2019-08-08.

这篇关于gcc size_t和sizeof算术转换为int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆