7

我有以下 C 代码:

typedef unsigned char uint8_t;

void main(void) {
    uint8_t a = 1, b = 2, res;
    res = a + b;
}   

当我使用 编译此代码时gcc -Wconversion,我收到以下警告:

test.c: In function 'main':
test.c:5:10: warning: conversion to 'uint8_t' from 'int' may alter its value [-Wconversion]

有人可以解释为什么会出现这个警告吗?所有三个变量都是 type uint8_t,所以我不太明白它的int来源。

4

3 回答 3

10

我真的不明白从哪里来int

int来自C语言标准。算术运算符的所有操作数在执行它们的操作之前都会被提升。在这种情况下uint8_t被提升为int,因此您需要强制转换以避免警告:

res = (uint8_t)(a + b);

以下是标准如何定义整数促销:

6.3.1.1 如果anint可以表示原始类型的所有值,则将该值转换为an int;否则,将其转换为unsigned int. 这些被称为整数促销。

因为int可以容纳 , 的所有可能值uint8_tab被提升为int用于加法运算。

于 2014-01-24T14:46:12.613 回答
4

只是为了添加有关整数促销的现有答案,可能还值得解释一下-Wconversion警告您的内容。

因为ab都是uint8_ts,所以 的结果a + b可能不适合另一个uint8_t。通过将结果分配回 a uint8_t,您可以强制编译器执行可能会更改值的转换。因此,该res变量可能实际上并不代表 的实际值a + b

例如,如果ab都是0xff,那么:

  • a + b0x1fe并且有类型int
  • (uint8_t)(a + b)0xfe
于 2014-01-24T15:02:45.110 回答
0

您应该阅读有关 C 的int 提升规则的更多信息。这是规则,所以编译器必须遵守。没有它,一些“琐碎”的代码将无法工作(如您所料)。例如

char d[4] = {0xFF, 0xFE, 0x80, 40};
int i = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
int j = d[2] - d[0]*d[1];

在一些用于 8 位微控制器的编译器中,有一个选项可以禁用 C 标准构造以加快数学运算速度,因为总是将 char 提升为 int 来进行数学运算可能会导致不必要的操作并减慢处理速度。它还消耗更多内存,这在此类嵌入式系统中是有价值的。当然,它会使某些代码无法移植或根本无法工作,但这就是权衡。

现代微处理器是 16 位或更多,因此使用 char 不会使您免于任何操作,但也可能会增加代码大小和速度,因为在每次操作之前/之后进行符号调整。除了加载/存储和符号扩展之外,大多数 RISC 体系结构甚至没有对不同于其本机大小的操作数进行操作的指令。因此建议对所有临时对象使用原生 int 大小。小于本机寄存器大小的类型应仅用于可能增加高速缓存未命中的非常大的数组、从某些其他类型的内存保存或读取数据或与其他系统/库兼容的情况

于 2014-01-24T16:43:40.433 回答