如何以单字节精度可移植地执行指针算法?
请记住:
char
在所有平台上都不是1个字节sizeof(void) == 1
仅作为GCC的扩展名答案 0 :(得分:19)
您的假设有缺陷 - sizeof(char)
定义在任何地方都是1。
从C99 standard (TC3),在第6.5.3.4节(“sizeof operator”)中:
(第2段)
sizeof运算符产生大小 (以字节为单位)其操作数,可以 是表达还是表达 带括号的类型名称。
(第3段)
当应用于具有的操作数时 键入char,unsigned char或signed char,(或合格的版本 结果是1。
当这些结合在一起时,很明显在C中,无论char的大小是多少,该大小都是“字节”(即使在某个给定平台上超过8位)。
因此char
是最小的可寻址类型。如果您需要以小于char
的单位进行寻址,那么您唯一的选择是一次只读char
并使用按位运算符来屏蔽您想要的char
部分
答案 1 :(得分:6)
答案 2 :(得分:3)
sizeof(char)
为1
。即使char
使用9位或更多位。
所以你可以这样做:
type *pt;
unsigned char *pc = (unsigned char *)pt;
并使用pc
进行算术运算。 使用上面的强制转换将pc
分配给pt
是C标准的未定义行为。
如果char
超过8位宽,则不能在可移植(ANSI / ISO)C中进行字节精度指针运算。这里,通过 byte ,我的意思是8位。这是因为基本类型本身大于8位。
答案 3 :(得分:3)
根据标准char
是最小的可寻址数据块。您无法更精确地解决问题 - 您需要手动打包/拆包。
答案 4 :(得分:1)
将指针投射到uintptr_t
。这将是一个无符号整数,它是指针的大小。现在对它进行算术运算,然后将结果强制转换为要取消引用的类型的指针。
(请注意intptr_t
已签名,这通常不是您想要的!除非您有充分的理由不坚持uintptr_t
,否则更安全!)
答案 5 :(得分:0)
C99标准定义了一个字节长的uint8_t。如果编译器不支持此类型,则可以使用typedef定义它。当然,您需要一个不同的定义,具体取决于平台和/或编译器。将所有内容捆绑在一个头文件中,并在任何地方使用它。
答案 6 :(得分:0)
我不明白你在GCC中sizeof(void)
为1时想说的是什么。虽然类型char
理论上可能包含多于1个底层机器字节,但在C语言中sizeof(char)
为1且始终为1.换句话说,从C语言的角度来看,{{1}总是1“字节”(C字节,而不是机器字节)。一旦你理解了这一点,你也会明白在GCC中char
为1对你没有任何帮助。在GCC中,sizeof(void)
指针上的指针算法与void *
指针上的指针算法完全相同,这意味着如果在某个平台上char *
不适合您,那么{ {1}}对您无效。
如果某些平台char *
对象由多个机器字节组成,则访问较小单元内存而不是完整void *
对象的唯一方法是使用按位运算来“提取”和“修改” “完整char
对象的必需部分。 C语言无法直接处理小于char
的任何内容。再次char
始终是C字节。