当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_t
为uintptr_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字节。