这是我发现的奇怪内容:
当我具有三个元素的char *并将其分配为“ 21”时,
打印出来的s的short int值似乎是12594,与二进制的0010001 0010010相同,对于单独的char则为49 50。但是根据ASCII图表,“ 2”的值为50,而“ 1”的值为49。
当我将字符向右移*(short*)s >>= 8
时,结果与(1.)一致,即为'1'或49。但是在我分配了字符*s = '1'
之后, s的打印字符串也似乎是“ 1”,我之前认为它会变成“ 11”。
我对现在如何将位存储在char中感到困惑,希望有人能对此进行解释。
以下是我使用的代码:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("%lu,%lu\n",sizeof(char), sizeof(short));
char* s = malloc(sizeof(char)*3);
*s = '2', *(s+1) = '1', *(s+2) = '\0';
printf("%s\n",s);
printf("%d\n",*(short int*)s);
*(short*)s >>= 8;
printf("%s\n",s);
printf("%d\n",*(short int*)s);
*s = '1';
printf("%s\n",s);
return 0;
}
输出为:
1,2
21
12594
1
49
1
此程序是使用gcc在macOS上编译的。
答案 0 :(得分:4)
您需要在这里对“字节序”的概念有所了解,可以将值表示为“小字节序”和“大字节序”。
我将跳过有关涉及不确定行为的合法性的讨论。
(不过,这是伦丁提供的相关链接,来源:
What is the strict aliasing rule?)
但是让我们看一下内存中的一对字节,低位地址包含50,高位地址包含49:
50 49
您通过显式设置低字节和高字节(通过char
类型)来完全按照这种方式进行介绍。
然后阅读它们,迫使编译器将其视为short
,这是系统上的两个字节大小的类型。
可以使用不同的“意见”来创建编译器和硬件,以更好地表示两个连续字节中的两个字节值。这叫做“ endianess”。
两个完全符合标准的编译器可以起到以下作用:
要返回的short
是
他们实际上并没有这样做,这是一种在硬件中实现的效率更高的机制,但关键是,即使是在硬件隐式实现中也可以做到这一点。
答案 1 :(得分:1)
您将以别名所不允许的方式通过别名类型重新解释表示形式:您可以像对待char数组一样处理short值,但不能相反。这样做可能会导致优化编译器出现奇怪的错误,这些编译器可能假设该值从未初始化,或者可能优化出包含未定义行为的完整代码分支。
然后,您的问题的答案称为“耐力”。在大字节序表示中,最高有效字节的最低地址(258或0x102将按该顺序表示为2字节0x01,0x02),而在小字节序表示中,最低有效字节的最低地址(0x102表示为0x02、0x01(按此顺序)。
您的系统恰好是小端的。