当我离开已签名的字符时,我不认为我完全理解c编译器中发生了什么。我用值0x8d<<初始化它了3,它给了我一个警告:隐式常量转换溢出。我假设它是因为它给了一个很大的char值,但是当我手工完成时我会得到104作为答案。
所以这意味着当价值被转移时它正在做
10001101 << 3 = 10001101000
而不是
10001101 << 3 = 01101000
想出来,但这是代码:
signed char testChar = 0x8d << 3;
printf("testChar : %d\n", testChar);
只需要正常初始化它然后将它转移到另一条线上,超级简单的东西。
答案 0 :(得分:1)
您的问题很混乱:您是否正在使用值0x8d << 3
初始化已签名的字符?这显然是实现定义为值超出类型范围并且类型已签名。编译器发出警告,因为精度损失是明确的。
相反,如果你的意思是左移一个签名的字符,左移一个值为0x8d
的签名字符,这又是不正确的:除非char
有超过8位,有符号的char不能具有0x8d的值。它的值-115
可以具有相同的位模式。左移这将以这种方式计算:
char
值首先提升为int
。int
值左移3但位置:相当于乘以8。结果值为-920
。此值不适合char
。将其存储到char
是实现定义的。最可能的结果是char
值为104
。
修改强>
您发布了实际代码:
signed char testChar = 0x8d << 3;
printf("testChar : %d\n", testChar);
如果char
是8位,则赋值具有实现定义的行为,因为1128
超出了类型signed char
(-128..127)的范围,这是大多数现代处理器上的行为是掩盖高阶位并将8个低阶位存储到目标字节中,就好像它是unsigned char
一样。在您的情况下,结果是1128 & 255
- &gt; 104
。
答案 1 :(得分:0)
您还没有显示您的实际代码(见下文),但您提供了足够的信息来推断它:
signed char c = 0x8d << 3;
常量0x8d
的类型为int
。将其左移3位会产生值0x468
,或等效1128
。
初始化会隐式地将该值从int
转换为signed char
。由于该值超出了signed char
的范围(可能会有-128
到+127
的范围,除非您使用非常奇怪的系统),结果是实现 - 定义。通常会丢弃高位,这会产生0x68
或104
的结果。
编译器警告您,您正在将值1128
转换为signed char
,这不足以容纳它。
也许您希望0x8d
属于signed char
类型?它不是。表达式的类型几乎总是由表达式本身决定,而不是由它出现的上下文决定。整数常量(十进制,十六进制或八进制)始终为int
类型,除非它们超过INT_MAX
的值,该值至少为32767
(可能为2147483647
)。 (或者除非他们有L
或U
这样的后缀,但这里没有相关内容。)
更新:
您已向我们展示了原始代码:
signed char testChar = 0x8d << 3;
printf("testChar : %d\n", testChar);
我希望这会产生警告,因为您用来初始化1128
的值testChar
会导致溢出。存储在testChar
中的值是实现定义的,但它很可能是104
,这是丢弃高位的结果。
如果您将班次分成单独的作业:
signed char testChar = 0x8d;
testChar = testChar << 3;
然后我期待相同的结果。但是值0x8d
太大而无法存储在signed char
中,因此转换会产生实现定义的结果 - 很可能是-115
。负值的左移有未定义的行为 - 但同样,它可能会产生-920
,转换为signed char
时可能会给你104
。
最终,您的问题的解决方案是做一些不同于您尝试做的事情。值0x8d << 3
将不适合signed char
,任何使其适合的尝试都必然会导致问题。通过调整代码,您可能会设法使编译器的警告静音,但您仍然在做一些没有用的事情。