标准C中的移位或算术运算的扩展

时间:2012-12-09 08:46:48

标签: c c99 c11

抱歉英语不好。

uint16_t a, c;
uint8_t b = 0xff;

a = b<<8;
c = b*10;

我们获得的ac的价值是多少?任意整数类型的情况是什么?

1 个答案:

答案 0 :(得分:0)

uint16_t a, c;
uint8_t b = 0xff;

a = b<<8;

首先,对<<的参数执行整数提升。常量8int,因此不会被转换。由于uint8_t的转化排名小于int的转化排名,uint8_t的所有值都可以表示为int,因此转换b - 保留其价值 - int。然后,生成的int值向左移动8位。

如果int只有16位宽,则值0xff * 2^8不能表示为int,然后移位调用未定义的行为 - 在n1570中为6.5.7(4)并且C99:

  

如果E1具有带符号类型和非负值,并且E1×2 E2 在结果类型中可表示,那么这就是结果值;否则,行为未定义。

否则,结果为255*256 = 65280 = 0xFF00。由于该值可在a类型中表示,因此将int转换结果转换为uint16_t会保留该值;如果结果超出范围(例如,如果移位距离为9 [且int足够宽]),则将以模2^16为模,以获得0范围内的值2^16 - 1的{​​{1}}。

uint16_t

通常的算术转换是在c = b*10; 的操作数上执行的。两个操作数都具有整数类型,因此首先执行整数提升。由于*10且所有int类型的值都可以表示为b,因此整数提升会为两个操作数提供相同的类型int ,通常的算术转换不需要任何进一步的转换。乘法在int类型上完成,其结果int再次可以在2550类型中表示,因此在存储值之前转换为cuint16_t中保留了值。

  

任意整数类型的情况是什么?

c

  1. 整数促销;转换等级小于或等于<<(和int)[宽度unsigned int<=]的整数类型的整数类型的值/表达式,类型为(unsigned) int_Boolintsigned int的位域将转换为unsigned intintunsigned int,如果可以的话表示原始类型的所有值,否则为int

  2. 如果(提升的)右操作数(移位距离)为负或大于或等于宽度(值位数加符号位;有一个符号位或无符号位)(已提升)左操作数,行为未定义。如果(提升的)左操作数的值为负,则行为未定义。如果(提升的)左操作数的类型是无符号的,则结果为unsigned int,减少模value * 2^distance。如果(提升的)左操作数的类型是有符号且值为非负,则结果为2^width如果在类型中可表示,则行为未定义。

  3. 如果2.中没有出现未定义的行为,则结果将转换为存储它的变量的类型。

    • 如果目标类型为value * 2^distance(或其别名),则非零结果将转换为1,零结果将转换为0,否则
    • 如果结果可以在目标类型中表示,则保留其值,否则
    • 如果目标类型是无符号的,则结果将以模_Bool为模,否则为
    • 结果以实现定义的方式转换,或者引发实现定义的信号。
  4. 2^width

    1. 执行通常的算术转换,以便两个(转换的)操作数具有相同的类型。
    2. 乘法在结果类型中执行;如果这是有符号整数类型并且乘法溢出,则行为未定义。
    3. 结果将以与上述相同的方式转换为目标类型。

    4. 这就是如何定义抽象机器,如果实现可以以另一种方式实现相同的结果(定义行为),它可以在as-if规则下随心所欲地做。