C 为什么对无符号字符之间的加法进行隐式转换?

C 为什么对无符号字符之间的加法进行隐式转换?,c,integer-promotion,compound-assignment,C,Integer Promotion,Compound Assignment,GCC警告此代码: unsigned char i = 1; unsigned char j = 2; i += j; 说: 似乎j被隐式转换为int 为什么添加相同类型的变量会发生隐式转换?C要求整数升级,引用 在表达式中可以使用int或unsigned int时,可以使用以下内容: 整数类型(int或unsigned int除外)的对象或表达式,其整数转换秩小于或等于int和unsigned int的秩 如果int可以表示原始类型的所有值(受位字段宽度的限制),则该值将转换为int 因

GCC警告此代码:

unsigned char i = 1;
unsigned char j = 2;
i += j;
说:

似乎
j
被隐式转换为
int


为什么添加相同类型的变量会发生隐式转换?

C要求整数升级,引用

在表达式中可以使用int或unsigned int时,可以使用以下内容:

  • 整数类型(int或unsigned int除外)的对象或表达式,其整数转换秩小于或等于int和unsigned int的秩
如果int可以表示原始类型的所有值(受位字段宽度的限制),则该值将转换为int

因此,在这样的表达式中使用
unsigned char
变量,并将其转换为
int
,因为
i+=j
在功能上等同于
i=i+j

如果确定结果在
无符号字符的范围内,则只需在赋值之前对加法结果应用强制转换,如下所示:

i = (unsigned char)(i + j)

以下是C11标准草案在§5.1.2.3(第15页)中关于(几乎)这种情况的说明:

例2

在执行片段时

char c1, c2;
/* ... */
c1 = c1 + c2;
“整数升级”要求抽象计算机 将每个变量的值提升为
int
size,然后将两个变量相加
int
s并截断总和。如果可以添加两个
char
s 无§5.1.2.3环境15 ISO/IEC 9899:201x委员会草案 -2011年4月12日N1570溢出,或用溢出包装无声地 产生正确的结果,实际执行只需要产生 同样的结果,可能省略了促销活动


所以,这是因为标准要求这样做。如果您查看生成的代码,很可能编译器足够聪明,在实践中根本不进行转换。

C就是这样工作的。出于提高效率的历史原因,存在到字长有符号整数的隐式转换。正确的术语是隐式转换。Cast意味着程序员使用操作符
(type)
,因此它总是显式的。强制转换将强制转换,但在没有强制转换时也可能发生转换。@Lundin已修复。谢谢。这很有效,但我认为在这种情况下,
char
数据类型使用不当。我的意思是,为什么一开始就要将用于文本
1
2
的存储声明为
char
s?如果存储位置要同时保存整数和字符,则可以很容易地使用整数类型,因为字符使用较小的存储。@Lym-一个原因是空间方面的考虑。在一个完全基于主机的系统中,您通常不会想到这一点,但是对于较小的偏移量,您可能会觉得有义务选择最小的类型。(当然,
uint8\u t
是一个更好的选择)。如果你不介意我问你,你是否曾经发现自己处于这种情况下或阅读过采用这种方法的代码。在我看来,由于截断而愿意丢失一些数据在任何情况下都是个坏主意。只是想找个案例研究。@Lym-我自己?我没有使用小于整数的数据类型。但我已经读了很多关于嵌入式编程的书,了解到在可用空间严重受限的情况下,可能会有不同的考虑因素。我想我好奇的另一件事是,当一个类型转换为较低类型时,是否定义了类似于[看起来是这样的]的行为。谢谢你的解释。
char c1, c2;
/* ... */
c1 = c1 + c2;