如何存储char数组?

时间:2018-07-05 05:58:32

标签: c char bit

这是我发现的奇怪内容:

当我具有三个元素的char *并将其分配为“ 21”时,

  1. 打印出来的s的short int值似乎是12594,与二进制的0010001 0010010相同,对于单独的char则为49 50。但是根据ASCII图表,“ 2”的值为50,而“ 1”的值为49。

  2. 当我将字符向右移*(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上编译的。

2 个答案:

答案 0 :(得分:4)

您需要在这里对“字节序”的概念有所了解,可以将值表示为“小字节序”和“大字节序”。

我将跳过有关涉及不确定行为的合法性的讨论。
(不过,这是伦丁提供的相关链接,来源:
What is the strict aliasing rule?

但是让我们看一下内存中的一对字节,低位地址包含50,高位地址包含49:

50 49

您通过显式设置低字节和高字节(通过char类型)来完全按照这种方式进行介绍。

然后阅读它们,迫使编译器将其视为short,这是系统上的两个字节大小的类型。

可以使用不同的“意见”来创建编译器和硬件,以更好地表示两个连续字节中的两个字节值。这叫做“ endianess”。

两个完全符合标准的编译器可以起到以下作用:

要返回的short

  • 取低位地址的值,再乘以256,再取高位地址的值
  • 取高位地址的值,再乘以256,再取低位地址的值

他们实际上并没有这样做,这是一种在硬件中实现的效率更高的机制,但关键是,即使是在硬件隐式实现中也可以做到这一点。

答案 1 :(得分:1)

您将以别名所不允许的方式通过别名类型重新解释表示形式:您可以像对待char数组一样处理short值,但不能相反。这样做可能会导致优化编译器出现奇怪的错误,这些编译器可能假设该值从未初始化,或者可能优化出包含未定义行为的完整代码分支。

然后,您的问题的答案称为“耐力”。在大字节序表示中,最高有效字节的最低地址(258或0x102将按该顺序表示为2字节0x01,0x02),而在小字节序表示中,最低有效字节的最低地址(0x102表示为0x02、0x01(按此顺序)。

您的系统恰好是小端的。