void 大小未知时的指针算术
在 Visual Studio C++ 版本 9(可能还有其他版本)中,以下代码:
int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;
error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size
此代码在 GCC 下工作,它处理 sizeof(void)
为 1
。
是否有某种方法可以解决此限制,因为出于指针算术的目的而显式转换为 char * 会增加混乱(void *
被很好地识别并用作指向的无类型指针原始内存)。
Update0
- 请注意,我很清楚 标准的存在。
- 我想要做原始指针 算术。
- 我采用
sizeof(void)
来 表明我很清楚这个事实 它不是1
是 问题的原因。 - 代码 例子只是为了证明什么 需要生成错误。
- 我知道这不是使用
void
的“正常”方式,但这是 C,并且这些事情会发生。 - 是的,人们需要在低层次上做到这一点。我不追求为什么,我追求如何。如果你想知道为什么,请查看一些内核源代码,或者你友好的 glibc。
Update1
这个问题似乎引起了很大的混乱。问题不在于为什么 sizeof(void) == 1
不是标准的,而是在不标准时该怎么办。
在要进行单字节指针算术的情况下,事实证明,转换为 char *
是正确的答案,而不是因为 *(void *)
没有大小,但因为标准实际上保证 *(char *)
始终为 1
。因此,出于原始指针算术的目的,使用 char *
始终是正确的,并且与具有 GCC 扩展的 void *
一致。
为了进一步强调这一点,void *
是指向无类型内存的指针的正确选择,char *
是为原始指针算术转换的正确类型< /强>。
In Visual Studio C++ version 9 (and probably other versions too), the following code:
int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;
error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size
This code works under GCC, which treats sizeof(void)
as 1
.
Is there some way around this limitation, as casting explicitly to char *
for purposes of pointer arithmetic adds to the confusion (void *
is well recognised and used as a typeless pointer to raw memory).
Update0
- Please note, I'm well aware of the
existence of the standard. - I want to do raw pointer
arithmetic. - I take
sizeof(void)
to
show that I'm well aware the fact
that it isn't1
is the
cause of the problem. - The code
example is simply to demonstrate what
is required to generate the errors. - I know this isn't a "normal" way to use
void
, but this is C, and these things happen. - Yes, people need to do this at low-level. I'm not after why, I'm after how. If you want to know why, take a look at some kernel source, or your friendly glibc.
Update1
It seems this question has generated a great deal of confusion. The question is not about why having sizeof(void) == 1
is not standard, but what to do when it isn't.
In the instance that single-byte pointer arithmetic is to be done, it turns out that casting to char *
is the correct answer, not because *(void *)
has no size, but because the standard actually guarantees that *(char *)
is always 1
. Therefore the use of char *
is always correct, and congruent with void *
with the GCC extension for the purposes of raw pointer arithmetic.
To further reinforce the point, void *
is the correct choice for pointers to typeless memory, and char *
is the correct type to cast to for raw pointer arithmetic.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
从技术上讲,增加指针应该是增加它所指向的对象的大小。虚空指的是虚无,所以大小未知。
对于某些编译器来说,让您增加 void 指针是一件好事。
强制转换很烦人,因为您必须将其强制转换为另一个指针,然后再返回,或者做一些尴尬的事情,例如
(*(char *)&voidptr) += 6
就我个人而言,我只是出于算术目的将其声明为
char *
Incrementing a pointer is technically supposed to increment it by whatever size of thing that its pointing at. Void points at nothing, so the size is unknown.
Its a nicety for some compilers to let you increment void pointers.
Casting is annoying, because you have to either cast it to another pointer, and then back, or do something awkward like
(*(char *)&voidptr) += 6
Personally, I'd just declare it as a
char *
for purposes of arithmetic在 C 语言中,
sizeof
不能应用于不完整类型。void
是不完整类型,这就是为什么您不能将其用作sizeof
的操作数。C 也不支持
void *
指针的指针算术。为了与指针算术一起使用,指针必须指向对象类型,而void
则不然。GCC 允许将两者作为奇怪的语言扩展。
In C language
sizeof
cannot be applied to incomplete types.void
is an incomplete type, which is why you can't use it as operand ofsizeof
.Pointer arithmetic of
void *
pointers is also not supported in C. In order to be used with pointer arithmetic the pointer has to point to object type, whichvoid
is not.GCC allows both as a weird language extension.
void *
意味着“指向未知的指针”,因此向 void 指针添加 6 是未定义的,因为您要求编译器将指针前进“6 个未知对象的大小”。
你不应该这样做。
void *
is meant to imply "pointer to unknown"Adding 6 to a void pointer is therefore undefined, because you're asking the compiler to advance the pointer by "the size of 6 unknown objects".
You should not be doing it.
这里有两个不同的问题。第一个用于
void
,第二个用于void*
。它们是不同的类型,除了名称之外几乎没有共同点。void
主要用于函数声明/定义(作为返回类型或表示“不带参数”)。您永远不可能拥有void
类型的对象。曾经。所以很难看出有必要找出那个不存在的物体的大小。 GCC 的行为是非标准的,是有意的扩展。然而,我相信他们选择了 sizeof(void) == 1 ,因为 C++ 标准要求每个对象至少占用一个字节的空间。void*
表示“指向真实数据的指针,但没有相关的类型信息”。void*
是完全有可能的;你会经常遇到他们。但是,由于类型信息被忽略,因此您无法对指针进行太多操作。这是设计使然,因为如果您不知道自己拥有什么,您就真的不知道可以用它做什么。但如果您想将内存视为字节集合,那么 char* 就可以做到。
char
在任何地方都是一个字节。字节串是char*
。如果您觉得这很奇怪,请使用byte*
(您将byte
定义为unsigned char
)。There are two different questions here. The first is for
void
, and the second forvoid*
. They are different types, and have little in common beside the name.void
is used mainly for function declarations/definitions (as the return type or to mean "takes no arguments"). You can't ever possibly have an object of typevoid
. Ever. So it's hard to see a need to find out the size of that nonexistent object. GCC's behavior is nonstandard, and an intentional extension. However, I believe they chosesizeof(void) == 1
because the C++ standard requires every object to take at least one byte of space.void*
means "pointer to real data, but without the relevant type information." It is entirely possible to havevoid*
; and you will run into them, a lot. However, because the type information is ignored you can't manipulate the pointer much. This is by design, because if you don't know what you have you really don't know what you can do with it.But if you want to treat the memory as a collection of bytes then
char*
does that. Achar
is one byte, everywhere. A string of bytes is achar*
. If you find this weird, usebyte*
(where you definebyte
as something likeunsigned char
).我至少可以在第一行看到错误 - 你有 sizeof(void) 并且它应该是 sizeof(void*),不是吗?
I can see the error on the first line at least - you have sizeof(void) and it should be sizeof(void*), no?
为了纯粹指向原始数据并按数据块占用的字节数递增该指针,我总是使用
char *
。然后,一旦我需要将其视为特定的东西,我就会将指针重新转换为相关的数据结构指针。递增void *
在编译器之间不可移植。For purely pointing at raw data and incrementing that pointer by the number of bytes a chunk of data occupies, I always use
char *
. I then recast the pointer to a relevant data structure pointer once I need to treat it as something specific. Incrementing avoid *
isn't portable among compilers.正确的。没有类型就意味着没有尺寸。
Correct. Not having a type means not having a size either.
看来正确答案是使用< code>char * 用于指针算术,因为
sizeof(char)
始终定义为 1,并且在任何平台上都具有最精细的可寻址粒度。简而言之,没有办法绕过这个限制,
char *
实际上是正确的方法。Matthias Wandel 拥有正确答案,但有不同的理由。
It would appear the correct answer is to use
char *
for pointer arithmetic, becausesizeof(char)
is always defined to be 1, and to be of the finest addressable granularity on any platform.So in short, there is no way around the limitation,
char *
is in fact the proper way to do it.Matthias Wandel had the right answer but with a different justification.