为什么unsigned char之间的加法会发生隐式转换?

Why implicit conversion occurs for addition between unsigned char?

GCC 警告此代码:

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

说:

warning: conversion to 'unsigned char' from 'int' may alter its value [-Wconversion]
   i += j;
        ^

似乎j被隐式转换为int
为什么同类型变量相加会发生隐式转换?

C 要求整数提升,引用 C11 N1570/6.3.1.1p2

The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of int and unsigned int.

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int

所以你的 unsigned char 变量用在这样的表达式中,因此被转换为 int,因为 i += j 在功能上等同于 i = i + j.

如果您确定结果在unsigned char的范围内,那么在赋值前只需对加法结果进行强制转换,就像这样:

i = (unsigned char)(i + j)

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

EXAMPLE 2

In executing the fragment

char c1, c2;
/* ... */
c1 = c1 + c2;

the ‘‘integer promotions’’ require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum. Provided the addition of two chars can be done without §5.1.2.3 Environment 15 ISO/IEC 9899:201x Committee Draft — April 12, 2011 N1570 overflow, or with overflow wrapping silently to produce the correct result, the actual execution need only produce the same result, possibly omitting the promotions.

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