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

发布于 2024-08-14 11:48:34 字数 215 浏览 7 评论 0原文

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

请记住:

  • 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 platforms
  • sizeof(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

与他有关 2024-08-21 11:48:34

您的假设是有缺陷的 - sizeof(char) 在任何地方都定义为 1。

来自 C99 标准 (TC3),第 6.5.3.4 节(“sizeof 运算符”):(

第 2 段)

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

(第3段)

当应用于具有
类型 char、unsigned char 或signed
char,(或合格版本
其中)结果为1。

当这些放在一起时,很明显,在 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)

The sizeof operator yields the size
(in bytes) of its operand, which may
be an expression or the
parenthesized name of a type.

(paragraph 3)

When applied to an operand that has
type char, unsigned char, or signed
char, (or a qualified version
thereof) the result is 1.

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 a char, your only choice is to read a char at a time and use bitwise operators to mask out the parts of the char that you want.

水染的天色ゝ 2024-08-21 11:48:34

sizeof(char) 始终返回 1,在 C 中 和 C++char 始终为一字节长。

sizeof(char) always returns 1, in both C and C++. A char is always one byte long.

梦晓ヶ微光ヅ倾城 2024-08-21 11:48:34

根据标准,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.

笔芯 2024-08-21 11:48:34

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

所以你可以这样做:

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

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

如果 char 更多如果宽度小于 8 位,则无法在可移植 (ANSI/ISO) C 中执行字节精度指针算术。这里,字节 指的是 8 位。这是因为基本类型本身大于 8 位。

sizeof(char) is guaranteed to be 1 by the C standard. Even if char uses 9 bits or more.

So you can do:

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

And use pc for arithmetic. Assigning pc to pt 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.

靑春怀旧 2024-08-21 11:48:34

将指针转换为 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 to uintptr_t unless you have a good reason not to!)

陌伤ぢ 2024-08-21 11:48:34

我不明白你想用 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 type char might theoretically consist of more than 1 underlying machine byte, in C language sizeof(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 that sizeof(void) being 1 in GCC does not help you in any way. In GCC the pointer arithmetic on void * pointers works in exactly the same way as pointer arithmetic on char * pointers, which means that if on some platform char * doesn't work for you, then void * 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 full char object would be to use bitwise operations to "extract" and "modify" the required portions of a complete char object. C language offers no way to directly address anything smaller than char. Once again char is always a C-byte.

再可℃爱ぅ一点好了 2024-08-21 11:48:34

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文