当 sizeof(char) != 1 时,C 中的字节精度指针算术
如何以单字节精度可移植地执行指针算术?
请记住:
char
在所有平台上都不是 1 个字节sizeof(void) == 1
只能作为 GCC 中的扩展使用- ,而某些平台可能具有指针 deref 指针对齐限制,算术可能仍然需要比最小基本 POD 类型的大小更细的粒度
How can one portably perform pointer arithmetic with single byte precision?
Keep in mind that:
char
is not 1 byte on all platformssizeof(void) == 1
is only available as an extension in GCC- While some platforms may have pointer deref pointer alignment restrictions, arithmetic may still require a finer granularity than the size of the smallest fundamental POD type
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您的假设是有缺陷的 -
sizeof(char)
在任何地方都定义为 1。来自 C99 标准 (TC3),第 6.5.3.4 节(“sizeof 运算符”):(
第 2 段)
(第3段)
当这些放在一起时,很明显,在 C 中,无论 char 大小如何,该大小都是“字节”(即使在某些给定平台上超过 8 位)。
因此,
char
是最小的可寻址类型。如果您需要以小于char
的单位进行寻址,您唯一的选择是一次读取一个char
并使用按位运算符来屏蔽char
的部分>char 你想要的。Your assumption is flawed -
sizeof(char)
is defined to be 1 everywhere.From the C99 standard (TC3), in section 6.5.3.4 ("The sizeof operator"):
(paragraph 2)
(paragraph 3)
When these are taken together, it becomes clear that in C, whatever size a char is, that size is a "byte" (even if that's more than 8 bits, on some given platform).
A
char
is therefore the smallest addressable type. If you need to address in units smaller than achar
, your only choice is to read achar
at a time and use bitwise operators to mask out the parts of thechar
that you want.sizeof(char)
始终返回 1,在 C 中 和 C++。char
始终为一字节长。sizeof(char)
always returns 1, in both C and C++. Achar
is always one byte long.根据标准,
char
是最小的可寻址数据块。您只是无法更精确地寻址 - 您需要手动进行打包/解包。According to the standard
char
is the smallest addressable chunk of data. You just can't address with greater precision - you would need to do packing/unpacking manually.C 标准保证
sizeof(char)
为1
。即使char
使用 9 位或更多。所以你可以这样做:
并使用
pc
进行算术。 通过使用上面的转换将pc
分配给pt
是 C 标准未定义的行为。如果
char
更多如果宽度小于 8 位,则无法在可移植 (ANSI/ISO) C 中执行字节精度指针算术。这里,字节 指的是 8 位。这是因为基本类型本身大于 8 位。sizeof(char)
is guaranteed to be1
by the C standard. Even ifchar
uses 9 bits or more.So you can do:
And use
pc
for arithmetic. Assigningpc
topt
by using the cast above is undefined behavior by the C standard though.If
char
is more than 8-bits wide, you can't do byte-precision pointer arithmetic in portable (ANSI/ISO) C. Here, by byte, I mean 8 bits. This is because the fundamental type itself is bigger than 8 bits.将指针转换为
uintptr_t
。这将是一个无符号整数,即指针的大小。现在对其进行算术,然后将结果转换回要取消引用的类型的指针。(请注意,
intptr_t
已签名,这通常不是您想要的!坚持使用uintptr_t
更安全,除非您有充分的理由不这样做!)Cast the pointer to a
uintptr_t
. This will be an unsigned integer that is the size of a pointer. Now do your arithmetic on it, then cast the result back to a pointer of the type you want to dereference.(Note that
intptr_t
is signed, which is usually NOT what you want! It's safer to stick touintptr_t
unless you have a good reason not to!)我不明白你想用 GCC 中的
sizeof(void)
为 1 来表达什么。虽然char
类型理论上可能包含超过 1 个底层机器字节,但在 C 语言中,sizeof(char)
为 1 并且始终恰好为 1。换句话说,从以下角度来看从C语言的角度来看,char
始终是1“字节”(C字节,而不是机器字节)。一旦你理解了这一点,你也会明白在 GCC 中sizeof(void)
为 1 对你没有任何帮助。在 GCC 中,void *
指针上的指针算术与char *
指针上的指针算术的工作方式完全相同,这意味着如果在某些平台上char *< /code> 不适合你,那么
void *
也不适合你。如果在某些平台上
char
对象由多个机器字节组成,则访问比完整char
对象更小的内存单元的唯一方法是使用按位运算来“提取”并“修改”完整char
对象的所需部分。 C 语言无法直接寻址小于char
的任何内容。再次强调,char
始终是 C 字节。I don't understand what you are trying to say with
sizeof(void)
being 1 in GCC. While typechar
might theoretically consist of more than 1 underlying machine byte, in C languagesizeof(char)
is 1 and always exactly 1. In other words, from the point of view of C language,char
is always 1 "byte" (C-byte, not machine byte). Once you understand that, you'd also understand thatsizeof(void)
being 1 in GCC does not help you in any way. In GCC the pointer arithmetic onvoid *
pointers works in exactly the same way as pointer arithmetic onchar *
pointers, which means that if on some platformchar *
doesn't work for you, thenvoid *
won't work for you either.If on some platform
char
objects consist of multiple machine bytes, the only way to access smaller units of memory than a fullchar
object would be to use bitwise operations to "extract" and "modify" the required portions of a completechar
object. C language offers no way to directly address anything smaller thanchar
. Once againchar
is always a C-byte.C99 标准定义了一个字节长的 uint8_t。如果编译器不支持此类型,您可以使用 typedef 来定义它。当然,您需要不同的定义,具体取决于平台和/或编译器。将所有内容捆绑在头文件中并在任何地方使用它。
The C99 standard defines the uint8_t that is one byte long. If the compiler doesn't support this type, you could define it using a typedef. Of course you would need a different definition, depending on the the platform and/or compiler. Bundle everything in a header file and use it everywhere.