为什么两个无符号整数之和的结果类型在 Clang 和 GCC 中不同

pan*_*des 1 c++ gcc clang compiler-warnings

我正在为我的模拟器编写一些低级代码,其中涉及大量 16 位和 8 位无符号整数。我-Wconversion在项目中启用了警告,所有警告都被视为错误 ( -Werror)。

考虑这个代码片段:

#include <cstdint>

int main ()
{
    uint16_t a = 4;
    uint16_t b = 6;
    uint16_t c = a + b;
}
Run Code Online (Sandbox Code Playgroud)

直到 GCC 9.3 使用-std=c++17 -Wconversion -Werroras 编译标志,出现以下错误:

<source>: In function 'int main()':
<source>:7:20: error: conversion from 'int' to 'uint16_t' {aka 'short unsigned int'} may change value [-Werror=conversion]
    7 |     uint16_t c = a + b;

      |                  ~~^~~
Run Code Online (Sandbox Code Playgroud)

但对于和 的任何编译器版本(测试直到),相同的代码不会给出此错误链接到编译器资源管理器。GCC 10.1ClangClang 5.0.0

所以我的问题如下:

  • IMO,两个相加unsigned ints不应隐式转换为int. 或者我的假设是错误的?
  • 为什么ClangGCC(直到 9.3)会产生不同的结果?标准是否对此操作规定了任何限制,还是由编译器供应商决定?
  • 发生了什么变化GCC 10.1?为什么不弹出此错误GCC 10.1

eer*_*ika 6

IMO,两个无符号整数的加法不应隐式转换为 int。或者我的假设是错误的?

这个假设并没有错。Unsigned int 永远不会隐式转换为 int。

然而,在您的系统上,uint16_t 恰好是 unsigned Short int。假设无符号短整数不会隐式转换为 int 是一个错误的假设。在大多数系统上它们被提升为 int。

最近有一个很好的问题,为什么促销要签署 int:/sf/answers/4342963131/

为什么 Clang 和 GCC(直到 9.3)产生不同的结果?

他们不这样做。两者都会提升为 int。根本没有对这一转变发出警告。该转换不是格式错误的,因此不需要发出诊断。

还是由编译器供应商决定?

诊断消息由编译器供应商自行决定(除非程序格式错误时需要诊断消息,除非另有说明)。

GCC 10.1 中发生了什么变化?为什么 GCC 10.1 不会出现此错误?

也许他们认为该警告在这种情况下没有用,因此将其删除。