gcc转换警告

时间:2014-01-24 14:43:09

标签: c casting int typedef

我有以下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]

有人可以解释为什么会出现此警告吗?所有三个变量都是uint8_t类型,因此我并不真正了解int的来源。

3 个答案:

答案 0 :(得分:9)

  

我真的不明白int的来源。

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

res = (uint8_t)(a + b);

以下是标准定义整数促销的方式:

  

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

由于int可以包含uint8_t的所有可能值,ab会被提升为int以进行添加操作。

答案 1 :(得分:4)

只是要添加有关整数促销的现有答案,也可能值得解释-Wconversion警告你的内容。

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

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

  • a + b0x1fe,类型为int
  • (uint8_t)(a + b)0xfe

答案 2 :(得分:0)

您应该阅读有关C int promotion rules的更多信息。这是规则,因此编译器必须遵守。没有它,一些“琐碎”的代码将无法工作(就像你预期的那样)。例如

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大小。小于本机寄存器大小的类型只应用于可能增加高速缓存未命中的非常大的数组,保存或读取某些其他类型的内存中的数据或与其他系统/库兼容的情况