【问题标题】:How was an array of char stored?char 数组是如何存储的?
【发布时间】:2018-07-05 05:58:31
【问题描述】:

这是我发现的一些奇怪的东西:

当我有一个由三个元素组成的 char* s,并将其分配为“21”时,

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

  2. 当我将 char 向右移动时,*(short*)s >>= 8,结果与 (1.) 一致,即 '1' 或 49。但在我分配 char *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

这个程序是在 macOS 上用 gcc 编译的。

【问题讨论】:

  • 你知道“字节序”吗?
  • 不,什么是“字节序”? @Yunnosch
  • 还是“小端”和“大端”?
  • 是的。定义您想要检测的字节序。研究它是如何变得可见和测试的。您可以在函数中执行此操作并返回布尔值或枚举“小”或“大”。例如,您显示的代码实际上就是这样的测试。如果你得到你所期望的,就返回一个字节序,如果没有,则返回另一个。然而,在不冒未定义行为的风险的情况下做到这一点更具挑战性。也许社区有一个想法。但是,您应该在单独的问题中询问它并事先搜索重复项。

标签: c char bit


【解决方案1】:

您需要对这里的“endianess”概念有所了解,即值可以表示为“little endian”和“big endian”。

我将跳过关于涉及未定义行为的合法性的讨论。
(这里有一个相关链接,由 Lundin 提供,学分:
What is the strict aliasing rule?

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

50 49

通过显式设置低字节和高字节(通过char 类型),您可以通过这种方式准确地介绍它们。

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

编译器和硬件可以用不同的“意见”来创建,关于什么是两个连续字节中两个字节值的良好表示。它被称为“字节序”。

两个完全符合标准的编译器可以像这样运行:

要返回的short

  • 取低地址的值,乘以256,加上高地址的值
  • 取高地址的值,乘以256,加上低地址的值

他们实际上并没有这样做,这是一种在硬件中实现的更有效的机制,但关键是即使是硬件中的实现也隐含地这样做或那样。

【讨论】:

    【解决方案2】:

    您正在以标准不允许的方式通过别名类型重新解释表示:您可以处理一个短值,就好像它是一个 char 数组,但不能相反。这样做可能会在优化编译器时导致奇怪的错误,这些错误可能会假定该值从未被初始化,或者可能会优化出包含未定义行为的完整代码分支。

    那么您的问题的答案称为字节序。在大端表示中,最高有效字节具有最低地址(258 或 0x102 将按顺序表示为 2 字节 0x01、0x02),而在小端表示中,最低有效字节具有最低地址(0x102 表示为0x02、0x01 的顺序)。

    您的系统恰好是小端系统。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-15
      相关资源
      最近更新 更多