How can one portably perform pointer arithmetic with single byte precision?
Keep in mind that:
char
is not 1 byte on all platformsYour 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.
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.
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.
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.
sizeof(char)
always returns 1, in both C and C++. A char
is always one byte long.
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.