为什么这段C代码:
#include <stdint.h>
uint8_t do_foo() {
uint8_t int8;
int8 = 0x80;
int8 = int8 + (uint8_t) 1;
return int8;
}
给这个编译器警告?
$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
$ gcc -c -Wall -Wextra -Wconversion test.c
test.c: In function ‘do_foo’:
test.c:6:10: warning: conversion to ‘uint8_t’ from ‘int’ may alter its value [-Wconversion]
int8 = int8 + (uint8_t) 1;
^
据我所知,右边的表达式绝对是uint8_t
类型,而不是int
类型。
答案 0 :(得分:6)
这是因为整数提升。
+
的操作数小于int
。因此,它们会被提升为int
,并且会在int
中进行添加。
对于int8
的分配,结果必须转换回uint8_t
,从而导致警告,因为该值可能不合适。
答案 1 :(得分:5)
为了简化编译器,最初定义的C仅允许对五种数字类型进行算术运算:int
,unsigned int
,long
,unsigned long
和{{1}因此意味着编译器只需要知道执行每个算术运算符的五种方法。此外,在二进制补码系统中,许多运算符可以对有符号和无符号整数类型使用相同的实现,因此只需要三个实现。尝试对上述任何一种类型或任何类型组合执行算术运算将导致“两个”操作数从上面的列表转换为相同的类型[左移和右移的右手操作符-shift类型独立于左侧。
虽然标准已经更改为将double
添加到可以执行算术的类型列表中,但您的示例使用的类型float
不在该列表中。通常,不在列表中的类型的值将转换为列表中的第一个类型,该类型可以包含相应类型的所有值,在您的情况下将为uint8_t
。将两个操作数提升为类型int
的添加并执行添加后,编译器会在尝试将结果分配回较小的类型时进行投诉。