Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I not do arithmetic on a cast of a void pointer?

Tags:

c

void foo(void *ptr, int numBytes)
{
    (char*)ptr += numBytes;
}

This doesn't compile in C. I know the alternative. But why does this not work? What is the problem?

like image 948
Brandon Yates Avatar asked Dec 15 '22 22:12

Brandon Yates


1 Answers

The problem

The problem is that (char*)ptr will not yield an lvalue, meaning that the value cannot be modified - one can see it as a temporary result of the cast, the cast will yield a rvalue of type char*.

It's semantically the same as if you'd have the below example, a cast yields a temporary value, such a value cannot be assigned a new value.

int x = 123;

(float)x += 0.12f; /* (1), illegal                                     */
                   /*  ^-- sementically equivalent to `123.f += 0.12f` */

Solution

In your question you have stated that you already know a workaround to this problem, but I'd like to explicitly write the solution to show how one can modify the value of ptr even when casts yields non-modifiable values.

  1. Take the address of your pointer to void,
  2. cast this address to a pointer to pointer to char,
  3. dereference that pointer, yielding a pointer to char,
  4. modify this yield lvalue as if the original void* was of type char*

*((char**)&ptr) += numbytes; // make `ptr` move forward `numbytes`

( Note: When dereferencing a pointer you get an lvalue, otherwise it would be impossible to change the value of the pointed to value located at an address stored in a pointer. )

like image 138
Filip Roséen - refp Avatar answered Jan 05 '23 08:01

Filip Roséen - refp