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

时间:2009-12-08 06:17:24

标签: c compiler-construction portability void-pointers pointer-arithmetic

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

请记住:

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

7 个答案:

答案 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)

sizeof(char)始终返回1,in both C and C++char总是一个字节长。

答案 2 :(得分:3)

C标准保证{p> 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字节。