如果我写类似 1<<8; whats 将是它的默认类型。默认情况下它是未签名的还是签名的,或者我必须键入它?基本上我的问题是:C 中涉及常量(正)的表达式的类型是什么(例如 2<<13)?难道每次我们都需要进行类型转换吗?
如果我想使用它(1<<8)作为签名类型转换是强制性的?像 short int x = (signed)(1<<8);
如果我写类似 1<<8; whats 将是它的默认类型。默认情况下它是未签名的还是签名的,或者我必须键入它?基本上我的问题是:C 中涉及常量(正)的表达式的类型是什么(例如 2<<13)?难道每次我们都需要进行类型转换吗?
如果我想使用它(1<<8)作为签名类型转换是强制性的?像 short int x = (signed)(1<<8);
结果的类型与提升的左操作数的类型相同。默认整数符号是有符号的,因此您的结果将默认有符号。
1) 一个 char 有 8 位。您必须使 1<<7 仅设置第一位。
2)无论该值是否有符号,位都是相同的。“=”左侧的数据类型决定了该值是否有符号。
你可以试试这个例子:我不得不移位 31 次,因为我的值被自动调用为 int。
#include <stdio.h>
int main() {
printf("size of int in Bytes: %d \n",sizeof(int)); //4
printf("my number: %d \n",1<<31); //-2147483648
printf("my number: %u \n",1<<31); //2147483648
return 0;
}
也许你可以研究这个来理解 %d 和 %u: printf reference
的结果1 << 8
有 type ,但如果是一个更大的值int
,它可能有不同的类型。1
当源代码有一个没有后缀的十进制数字时,它的类型是第一个int
, long int
, 或者long long int
可以表示该值的那个。因为这些类型的大小在不同的 C 实现中可能不同,所以数字的类型在不同的 C 实现中可能不同。例如,65536
可能int
在一个 C 实现long int
中和另一个中。
按位移位的结果具有(提升的)左操作数的类型。(此处的提升无关紧要,因为每个整数文字都已经是其提升所产生的类型。但是,如果您有char x;
, thenx
在表达式中使用时将受到提升。)
因此, 的类型1 << 8
是int
。
类型、提升和按位移位的交互可能很麻烦。新手程序员可能会使用1 << 31
设置了第 31 位来获取值。但是,在许多 C 实现中,此表达式具有未定义的行为,因为理想的数学结果 2 31在32 位int
的实现中不能表示为 a 。int
操作溢出,C 标准没有定义行为。
因此,通常将无符号值与按位移位运算符和按位逻辑运算符一起使用。代替1 << 31
,1u << 31
是首选。
一个特别讨厌的问题发生在unsigned char x; … x << 24
. 在这里,程序员认为他们通过使用无符号类型进行位操作做了正确的事情。不幸的是,整数提升规则(在正常的 C 实现中)将 an 转换unsigned char
为 an int
,而不是 an unsigned int
。因此, in x << 24
,x
成为有符号整数,并且移位可能会溢出,导致未定义的行为。
因此,任何使用位运算的程序员都必须学习整数提升规则和通常的算术转换,这些都记录在 C 标准的 C 2011 (N1570) 6.3.1.1 2 和 6.3.1.8 1 中。