Void Pointer Arithmetic

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 the struct 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* or float* & why char* 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-Pointers

In GNU C, addition and subtraction operations are supported on
pointers to void and on pointers to functions. This is done by
treating the size of a void or of a function as 1.

A consequence of this is that sizeof is also allowed on void and on
function types, and returns 1.



Related Topics



Leave a reply



Submit