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

问题描述 投票:0回答:3

我正在为我的仿真器编写一些低级代码,其中涉及大量的16位和8位无符号整数。我启用了 -Wconversion 在我的项目中,所有的警告都被视为错误(-Werrordon't} want to see a warning for some particular case.

#include <cstdint>

int main ()
{
    uint16_t a = 4;
    uint16_t b = 6;
    uint16_t c = a + b;
}

-std=c++17 -Wconversion -WerrorI ran into the same warning for doing a bit shift:

<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;

      |                  ~~^~~

Clang output with warnings enabled:But the assembly listing shows no sign of the phantom GCC 10.1 promotion others are referring to in this thread. Only Clang widths are used throughout:Clang 5.0.0https:考虑这个代码片段。直到GCC 9.3与

作为编译标志,给出以下错误。

  • 但是 unsigned ints同样的代码不会出现这个错误int 对于
  • 的任何编译器版本,以及对 Clang (测试到 GCC).
  • 鏈接GCC 10.1 到编译器资源管理器。GCC 10.1所以我的问题如下。
IMO,增加两个
c++ gcc clang compiler-warnings
3个回答
4
投票
为什么?

(直到9.3)会产生不同的结果?标准是否规定了对这个操作的限制,还是由编译器厂商来决定?是什么改变了

? 为什么这个错误没有出现在 ?

我正在为我的仿真器编写一些低级代码,其中涉及大量的16位和8位无符号整数。我在我的项目中启用了-Wconversion警告,所有的警告都被认为是错误(-Werror)。 我认为,两个无符号整数的加法不应该被隐式转换为一个int。还是我的假设有误?

这个

的假设并没有错。无符号的int永远不会被隐含地转换为int.然而在你的系统中,uint16_t恰好是无符号的。

然而在你的系统中,uint16_t恰好是无符号的。

短暂

int。假设无符号短ints没有被隐式转换为int是一个错误的假设。在大多数系统中,它们都被提升为int。

最近有一个关于

何以

晋级是为了签到。

https:/stackoverflow.coma620423302079303。


4
投票

它们并不一样。两者都会推广到int。一个只是没有警告转换。转换并不是错误的,所以没有要求发出诊断。unsigned int unsigned short还是由编译器厂商来决定?uint16_t诊断信息是由编译器厂商决定的(,除非另有规定,否则当程序格式不良时需要诊断信息)。unsigned short

GCC 10.1中改变了什么?为什么GCC 10.1没有弹出这个错误?int也许他们认为这个警告在这种情况下没有用,所以把它去掉了。+ int unsigned int没有增加两个

在您的代码中。事实上,你添加了两个 (int)4,因为 (int)6 是一个类型定义,用于 (int)10.c整数推广规则规定,任何比整数类型窄的整数类型都要比

的操作数,它作为 c 晋升为

(不是 -Wconversion 如你所料)。)#pragma所以涉及的步骤是

加到 -Wconversion 给予

然后再分配给

0
投票

你应该会发现,所有的编译器都会为

uint8_t left_shift(uint8_t a, uint8_t b) { return a << b; }

,代码的行为是有明确规定的。-Wconversion准则的行为是有明确规定的。

<source>:10:53: warning: implicit conversion loses integer precision: 'int' to 'uint8_t' (aka 'unsigned char') [-Wimplicit-int-conversion]

uint8_t left_shift(uint8_t a, uint8_t b) { return a << b; }
                                           ~~~~~~ ~~^~~~

是比较有争议的。 正如这段代码就是一个很好的例子,它经常会对定义好的代码给出警告。 除了不使用标志,或者用某种方式包装假阳性(也许是通过 int 或一个函数调用)。)byte有些人确实希望看到这段代码的警告,有些人不希望。 确切的情况是,在哪些情况下,警告会由

由于人们提交了错误报告,他们{do/godbolt.orgzeSVaQW]在gcc中不断变化。

left_shift(unsigned char, unsigned char):
        push    rbp
        mov     rbp, rsp
        mov     byte ptr [rbp - 1], dil
        mov     byte ptr [rbp - 2], sil
        movzx   eax, byte ptr [rbp - 1]
        movzx   ecx, byte ptr [rbp - 2]
        shl     eax, cl
        movzx   eax, al
        pop     rbp
        ret
© www.soinside.com 2019 - 2024. All rights reserved.