1

如何以单字节精度便携地执行指针运算?

请记住:

  • char在所有平台上都不是 1 字节
  • sizeof(void) == 1仅在 GCC 中作为扩展提供
  • 虽然某些平台可能有指针 deref 指针对齐限制,但算术可能仍需要比最小基本 POD 类型的大小更精细的粒度
4

7 回答 7

21

你的假设是有缺陷的 -到处都sizeof(char)定义为 1 。

C99 标准 (TC3)的第 6.5.3.4 节(“sizeof 运算符”)中:

(第 2 段)

sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或带括号的类型名称。

(第 3 段)

当应用于具有 char、unsigned char 或 signed char 类型(或其限定版本)的操作数时,结果为 1。

将这些放在一起时,很明显在 C 中,无论 char 大小是多少,该大小都是一个“字节”(即使在某些给定平台上超过 8 位)。

因此Achar是最小的可寻址类型。如果您需要以小于 a 的单位寻址char,您唯一的选择是char一次读取 a 并使用按位运算符屏蔽char您想要的部分。

于 2009-12-08T06:28:29.270 回答
6

sizeof(char)在 C 和 C++中总是返回 1 。Achar总是一个字节长。

于 2009-12-08T06:24:33.293 回答
3

sizeof(char)保证符合1C 标准。即使char使用 9 位或更多位。

所以你可以这样做:

type *pt;
unsigned char *pc = (unsigned char *)pt;

pc用于算术。 但是,使用上面的强制转换分配pcptC 标准是未定义的行为。

如果char超过 8 位宽,则不能在可移植(ANSI/ISO)C 中进行字节精度指针运算。这里,字节,我的意思是 8 位。这是因为基本类型本身大于 8 位。

于 2009-12-08T06:22:51.487 回答
3

根据标准char是最小的可寻址数据块。您只是无法更精确地解决问题 - 您需要手动进行打包/拆包。

于 2009-12-08T06:26:33.213 回答
1

将指针转换为uintptr_t. 这将是一个指针大小的无符号整数。现在对其进行算术运算,然后将结果转换回您要取消引用的类型的指针。

(请注意,intptr_t这是已签名的,这通常不是您想要的!uintptr_t除非您有充分的理由不这样做,否则坚持下去会更安全!)

于 2009-12-08T06:24:31.657 回答
1

我不明白你sizeof(void)在 GCC 中是 1 是想说什么。虽然 typechar理论上可能包含超过 1 个底层机器字节,但在 C 语言sizeof(char)中是 1 并且始终恰好是 1。换句话说,从 C 语言的角度来看,char始终是 1 个“字节”(C 字节,而不是机器字节)。一旦你理解了这一点,你也会明白sizeof(void)在 GCC 中成为 1 对你没有任何帮助。在 GCC 中,指针上的指针运算与指针上的指针运算的void *工作方式完全相同char *,这意味着如果在某些平台char *上不适用于您,那么void *也不适用于您。

如果在某些平台上char的对象由多个机器字节组成,那么访问比完整对象更小的内存单元的唯一方法是使用按位运算来“提取”和“修改”完整对象char的所需部分。charC 语言无法直接处理小于char. 再一次char总是一个 C 字节。

于 2009-12-08T06:31:21.230 回答
0

C99 标准定义了一个字节长的 uint8_t。如果编译器不支持这种类型,你可以使用 typedef 来定义它。当然,您需要不同的定义,具体取决于平台和/或编译器。将所有内容捆绑在一个头文件中并在任何地方使用它。

于 2009-12-08T06:21:41.077 回答