当sizeof(char)!= 1时,C中的字节精度指针算术

如何以单字节精度可移植地执行指针运算?

请记住:

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

你的假设存在缺陷 – sizeof(char) 定义为1。

根据C99标准(TC3) ,在6.5.3.4节(“尺寸操作员”)中:

(第2段)

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

(第3段)

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

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

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

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

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

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

所以你可以这样做:

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

并使用pc进行算术运算。 然而,使用上面的pc转换将pc分配给pt是C标准的未定义行为。

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

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

(注意intptr_t是签名的,这通常不是你想要的!坚持uintptr_t更安全,除非你有充分的理由不这样做!)

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

我不明白你想说的是在GCC中sizeof(void)为1。 虽然char类型理论上可能包含多于1个底层机器字节,但在C语言中sizeof(char)为1且始终精确为1.换句话说,从C语言的角度来看, char总是1“byte”(C -byte,而不是机器字节)。 一旦你理解了这一点,你也会明白在GCC中sizeof(void)为1对你没有任何帮助。 在GCC中, void *指针上的指针算法与char *指针上的指针算法完全相同,这意味着如果在某些平台上char *对你不起作用,那么void *也不适用于你。

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