Reputation: 2052
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?
Upvotes: 4
Views: 355
Reputation: 206667
That's because
(char*)ptr
is not an lvalue.
Try this instead:
void foo(void *ptr, int numBytes)
{
char* p = (char*)ptr;
p += numBytes;
}
Update
A brief explanation of various value types can be found at cppreference.com. This talks about value types in C++ but the core ideas translate to C.
For the purpose of this discussion,
An lvalue is an expression that identifies a non-temporary object or a non-member function.
You can take the address of an lvalue and assign to a different value.
Example:
int i;
int* p = &i;
i = 20;
In contrast,
A prvalue ("pure" rvalue) is an expression that identifies a temporary object (or a subobject thereof) or is a value not associated with any object.
The literal 42
is an rvalue. You cannot do:
int* p = &42;
42 = 53;
In this line,
char* p = (char*)ptr;
an lvalue (p
) is created from (char*)ptr
. Hence, it is possible to use:
p += numBytes;
Upvotes: 4
Reputation: 63832
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.
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. )
Upvotes: 5
Reputation: 11047
On the left side of an =
, you need an lvalue
. But (char*)ptr
is not an lvalue.
Upvotes: 3