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