Why can't I do arithmetic on a void index sheet?

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

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

+3
source share
3 answers

Problem

The problem is that (char*)ptr will not give an lvalue value, which means that the value cannot be changed - you can see it as a temporary result of the cast, the cast will give an rvalue of type char* .

This is semantically the same as if you had the example below, the cast gives a temporary value, this value cannot be assigned a new value.

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

Decision

In your question, you stated that you already know a workaround to this problem, but I would like to write a solution explicitly to show how you can change the ptr value, even if the cast gives unmodifiable values.

  • Take the address of the pointer to void,
  • sends this address to a pointer to a pointer to a char,
  • dereference this pointer by pointing to a pointer to char,
  • change this lvalue value 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 value, otherwise it would be impossible to change the value of the pointer to a value located at the address stored in the pointer.)

+4
source

On the left side = you will need an lvalue . But (char*)ptr not an lvalue.

+3
source

It's because

(char*)ptr not a value of l.

Try this instead:

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

Update

A brief description of the various types of values ​​can be found at cppreference.com . This talks about value types in C ++, but the main ideas translate to C.

For the purpose of this discussion

An lvalue value is an expression that identifies a non-temporal object or function that is not a member.

You can take the lvalue address and assign a different value.

Example:

 int i; int* p = &i; i = 20; 

On the contrary

The value prvalue ("pure" rvalue) is an expression that identifies a temporary object (or its subobject) or is a value not associated with any object.

Literal 42 is the value of r. You can not:

 int* p = &42; 42 = 53; 

In this line

  char* p = (char*)ptr; 

lvalue ( p ) is created from (char*)ptr . Therefore, you can use:

  p += numBytes; 
+3
source

Source: https://habr.com/ru/post/1205115/


All Articles