*= 做什么?

What does *= do?

嘿,我是 C 的新手,我想问一下为什么打印出来的是 4 而不是 260

#include <stdio.h>

int main()
{
    unsigned char x = 130;
    x *= 2;
    printf("%d\n", x);
}

*=运算符称为乘法赋值运算符,是shorthand用于将左操作数与右操作数相乘并赋值结果到左边的操作数。在这种情况下,它与:

x = x * 2;

这里整数提升首先发生,x * 2的结果确实是260

但是,unsigned char 通常只能携带 0 到 255(含)之间的值,因此当您尝试分配高于 255 和 260 % 256 == 4 的值时,结果会溢出(环绕)。

unsigned char只能包含0到256,当超过256时,强制从0到256。

根据语言规范,unsigned char 数据类型占用 1 个字节的内存,因此它可以存储 0-255 的值,如果您的值大于 255,它将从零开始溢出。所以 260(130 * 2) - 256 = 4 被分配给你的变量。 https://docs.microsoft.com/en-us/cpp/cpp/cpp-type-system-modern-cpp?view=msvc-170#fundamental-built-in-types

在复合赋值运算符的语句中

x*=2;

相当于

x = x * 2;

表达式的操作数 x 由于整数提升而转换为类型 int 并且表达式的结果确实等于 260。但是结果被分配给变量x 类型为 unsigned char.

unsigned char x=130;

值 260 不能存储在这样的对象中。由于 260 在内部是整数,因此表示为

0x00000104

然后对象中只存储值为 0x4 的最后一个字节并输出该值。

如果变量 x 的类型至少像

unsigned short x=130;

x *= 2 使用 乘法赋值运算符 x = x * 2 的简写符号,其中 x 仅计算一次。

这个小程序的行为很重要:

  • 乘法是在参数整数提升之后执行的,这意味着 x130 的值被提升为类型 int 并且乘法给出 260作为 int.
  • 通过重复减去 UCHAR_MAX+1(在您的系统上为 256),直到达到目标类型范围内的值,此值被转换为目标类型 unsigned char。因此 x 变成 260 % 256 = 4.
  • 因为它有一个小于int的整数类型,x在传递给printf时被提升为int,所以格式%d,它需要一个 int 值,定义了行为并产生 4.

请注意,对于 unsigned char 超过 8 位的特殊架构(例如:数字信号处理芯片),上面的一些讨论是无关紧要的,printf 可能会打印出 260 甚至有未定义的行为(如果 sizeof(int) == 1)。