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
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!)sizeof(char)
always returns 1, in both C and C++. Achar
is always one byte long.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.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.
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)
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.