Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c标准和位移位_C_Standards_Bit Shift - Fatal编程技术网

c标准和位移位

c标准和位移位,c,standards,bit-shift,C,Standards,Bit Shift,这个问题最初是由该代码的(意外)结果启发而来的: uint16_t t16 = 0; uint8_t t8 = 0x80; uint8_t t8_res; t16 = (t8 << 1); t8_res = (t8 << 1); printf("t16: %x\n", t16); // Expect 0, get 0x100 printf(" t8: %x\n", t8_res); // Expect 0, get 0 为什么(t8我认为你困

这个问题最初是由该代码的(意外)结果启发而来的:

uint16_t   t16 = 0;
uint8_t     t8 = 0x80;
uint8_t t8_res;

t16    = (t8 << 1);
t8_res = (t8 << 1);

printf("t16: %x\n", t16);    // Expect 0, get 0x100
printf(" t8: %x\n", t8_res); // Expect 0, get 0

为什么(t8我认为你困惑的根源可能是以下两种说法不相等:

t64 = (uint64_t) (((int) t64) << 31);
  • 每个操作数应为整数类型
  • 每个操作数应具有
    int
    类型

uint64\u t
是一个整数类型。

您在标准中发现了错误的规则:(相关规则类似于“通常的整数类型促销适用”。这就是第一个示例的要点。如果像
uint8_t
这样的整数类型的秩小于
int
,它将升级为
int
uint64_t
没有小于
int
unsigned
的秩,因此不会执行升级,并且
将遵守§6.5.7中的约束“每个操作数都应具有整数类型。”这是一个约束,意味着您不能对非整数类型(如浮点值或指针)使用按位移位运算符。它不会造成您注意到的效果

造成影响的部分在下一段中:

3.对每个操作数执行整数提升。结果类型为提升后的左操作数

整数促销如§6.3.1.1所述:

2.如果
int
或者可以使用无符号整数

  • 具有整数类型的对象或表达式,其整数转换秩小于或等于
    int
    的秩,并且
    无符号整数
  • 类型为
    \u Bool
    int
    有符号int
    无符号int
    的位字段
如果
int
可以表示原始类型的所有值,则该值 将转换为
int
;否则,将转换为
无符号
int
。这些被称为整数促销。所有其他类型都是 整数促销保持不变

uint8\u t
的等级低于
int
,因此该值被转换为
int
(因为我们知道
int
必须能够表示
uint8\u t
的所有值,考虑到这两种类型范围的要求)

排名规则很复杂,但它们保证具有较高排名的类型不能具有较低的精度。这意味着,实际上,不能通过整数提升将类型“降级”为精度较低的类型(可以将
uint64\u t
提升为
int
无符号int
,但前提是类型的范围至少为
uint64\u t


uint32\t的情况下,我不太明白为什么你说
//在第二次左移31位后,我会感到困惑,因为格雷格是,但我希望类型永远不会自动降级(缩小),只会升级(扩大)。根据我对标准的理解,t64=(uint64\t)((int)t64)N1124由C99标准组成,其中合并了前两个技术勘误。是相同的,但与所有三个TC相同。(没有重大差异。)确实,这是OP混淆的根源。@Pat:注意,
uint8\u t
也是一个整数类型,因此此规则对您在第一个示例中看到的行为不负责。正如所述,正是“常用算术转换”导致类型小于
int
的值被提升(至
int
无符号
)@caf阅读了Jens的评论后,我进一步修改了问题。有什么进一步的见解吗?编辑的主要问题,因为评论中不允许换行,请看一看?啊……第6.3.1.1节第2节的最后一点对我来说真的很重要。还有你最后的总结规则。我的C思维模式更像是“按需促销”(因此在结尾附加了uint8_t问题)。这个答案很有道理,谢谢你抽出时间。-帕特
{
uint64_t t64 = 1;
t64 <<= 31;
printf("t64: %lx\n", t64); // Expect 0x80000000, get 0x80000000
t64 <<= 31;
printf("t64: %lx\n", t64); // Expect 0x0, get 0x4000000000000000
}
t64 = (uint64_t) (((int) t64) << 31);
uint32_t << uint64_t
uint32_t t32 = 1;
uint64_t t64_one = 1;
uint64_t t64_res;

t64_res = t32 << t64_one;
{
uint16_t t16 = 0;
uint8_t t8 = 0x80;
uint8_t t8_one = 1;
uint8_t t8_res;

t16 = (t8 << t8_one);
t8_res = (t8 << t8_one);

printf("t16: %x\n", t16);
printf(" t8: %x\n", t8_res);
}

t16: 100
 t8: 0
uint32_t t32 = 1;
uint64_t t64_one = 1;
uint64_t t64_res;

t64_res = t32 << t64_one;
uint32_t t32 = 0xFF000;
uint64_t t64_shift = 16;
uint64_t t64_res;

t64_res = t32 << t64_shift;