Pointer arithmetic when void has unknown size [closed]
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;
Generates these errors:
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, a开发者_高级运维s 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.
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
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 of sizeof
.
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, which void
is not.
GCC allows both as a weird language extension.
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.
There are two different questions here. The first is for void
, and the second for void*
. 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 type void
. 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 chose sizeof(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 have void*
; 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. A char
is one byte, everywhere. A string of bytes is a char*
. If you find this weird, use byte*
(where you define byte
as something like unsigned char
).
I can see the error on the first line at least - you have sizeof(void) and it should be sizeof(void*), no?
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 a void *
isn't portable among compilers.
void * is well recognised and used as a typeless pointer to raw memory.
Correct. Not having a type means not having a size either.
It would appear the correct answer is to use char *
for pointer arithmetic, because sizeof(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.
精彩评论