Use of char* over void* in pointer arithmetic
Why Pointers to Characters Are Used
Why is desc cast to char*? … As
char*
has nothing to do with thestruct
in question…
In C, every object except a bit-field is composed of a sequence of bytes.1 Converting the address of an object to char *
yields a pointer to the first byte of the object, and you can access the individual bytes of the object using that pointer.
In standard C, pointer arithmetic uses units of the pointed-to type. For a pointer p
of type struct Test
, p+1
points to the next structure after p
, p+2
points to the structure after that, and so on. For a pointer q
of type char *
, q+1
points to the next char
after q, q+2
points to char
after that, and so on.
Thus, to access the individual bytes of an object, you can convert its address to a char *
and use that.
Why Other Kinds of Pointers Are Not Used
A more specific question could be, why not
int*
orfloat*
& whychar*
is used?
char *
is used because all objects in C, except bit-fields, are defined to be represented as sequences of bytes. They are not necessarily sequences of int
or float
. unsigned char *
and signed char *
may also be used, and unsigned char *
may be preferable due to complications from sign issues.
The C standard has special rules about accessing objects using character pointers, so it guarantees that accessing the bytes of an object this way will work. In contrast, accessing objects using int *
or float *
may not work. The compiler is allowed to expect that a pointer to an int
will not be used to access a float
object, and, when it is generating machine instructions for a program, it may write those instructions based on that expectation. Using a character pointer prevents the compiler from assuming that a char *
does not point to the same place as another kind of pointer.
Why Pointers to Void Work
Note: I used
void*
just to see if that works.
For pointer arithmetic to work, the compiler needs to know the size of the pointed-to object. When 1 is added to a pointer to a struct Test
, the compiler needs to know how many bytes to adjust the internal address by.
void
is an incomplete type. There are no void
objects, and void
has no size. (The size is not zero. There is no size.) Because of this, the C standard does not define any meaning for p+1
when p
is a void *
.
However, GCC defines arithmetic on void *
as an extension. It works as if void
had a size of 1 byte. Clang supports this too.
Because of this extension, doing arithmetic with void *
pointers is essentially the same as doing arithmetic with char *
pointers.
This extension is unnecessary; any code doing arithmetic on void *
could be rewritten to use char *
instead. Sometimes this requires extra casts to convert pointer types, and that could be the reason the extension was added to GCC (to reduce the amount of code required and make it look better).
You can disable this extension with the switches -Werror -Wpointer-arith
, or you can generally request closer conformance to standard C with -Werror -std=c18 -pedantic
. I used -Werror -std=c18 -pedantic
whenever possible, and I recommend it.
Footnote
1 Bit-fields are sequences of bits that are held in some larger container of bytes and may happen to coincide with bytes.
Can I do arithmetic on void * pointers in C?
It depends on compiler. Those that allow it consider sizeof(*(void *)) as 1.
EDIT: it's only for void pointer arithmetic. It would have no sense using in this case steps of sizeof(int) or of 0. The common expectations of someone who uses it would be the smallest possible step.
Void Pointer Arithmetic
Is there a better way than casting to
a char pointer?
No (except having a char *
instead of a void *
to begin with, so you don't have to cast it at all).
If this is not desirable or possible, then the only way is:
ptr = static_cast<char *>(ptr) + offset;
(Note: if you are doing this sort of stuff in C++, usually there is a much better solution. Unless you are an expert and you already ruled out every other alternative, I suggest you post a new question asking if there is a better way to do what you're trying to do!)
Preventing compilation of void** pointer arithmetic in C
I misunderstood what you were doing at first. I thought you were doing math on a void*
. That is not allowed by the C Standard, but is allowed by a GCC (and clang) extension that treats it as math on a char*
.
However, you are doing math on a void**
which is perfectly OK. A void*
is the size of a pointer and is not an undefined value. You can make arrays of void*
s and you can do pointer math on a void**
because it has a defined size.
So you will never get a warning for void**
math because it is not a problem.
Why is void pointer arithmetic allowed in gcc?
This is an extension supported by GCC. It treats a void *
like a char *
.
From the gcc docs:
6.24 Arithmetic on
void
- and Function-PointersIn GNU C, addition and subtraction operations are supported on
pointers tovoid
and on pointers to functions. This is done by
treating the size of avoid
or of a function as 1.A consequence of this is that
sizeof
is also allowed onvoid
and on
function types, and returns 1.
Related Topics
Load Resource as Byte Array Programmaticaly in C++
How to Find If a Variable Is Allocated in Stack or Heap
Why Are Designated Initializers Not Implemented in G++
Why Do I Need to Include Both the iOStream and Fstream Headers to Open a File
Const and Non Const Template Specialization
Using Std::Make_Unique with a Custom Deleter
Can You Start a Class Name with a Numeric Digit
Does Gdi+ Have Standard Image Encoder Clsids
How to Read a File at Compile Time
Openal: How to Create Simple "Microphone Echo" Programm
What Standard Clause Mandates This Lvalue-To-Rvalue Conversion
If Constexpr - Why Is Discarded Statement Fully Checked
Best Way to for C++ Types to Self Register in a List