C - expression must be modifiable value lvalue

I am confused why my compiler throws an error in the following state:

void funcExample (void * p_Buf, uint16_t len) { uint16_t i; for (i = 0; i < len; i++) { otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue } } 

but if I passed it before going to otherFunc, that would be fine, because no problem increases the non-void pointer:

 void funcExample (void * p_Buf, uint16_t len) { uint16_t i; uint8_t * p_Buf_8bit; p_Buf_8bit = (uint8_t *) p_Buf; for (i = 0; i < len; i++) { otherFunc (p_Buf_8bit++); } } 

Can the void pointer increase after casting it? I don’t understand something here?

+5
source share
4 answers

Role operators in c:

6.5.4. p5 The preceding expression, using the type name in brackets, converts the value of the expression for the specified type. This design is called cast. 104) A cast that indicates no conversion affects the type or value of the expression.

104) Listing does not give an lvalue. Thus, casting to a qualified type has the same effect as casting to an unqualified version of a type

But the unary operator ++ requires an lvalue, as indicated:

6.5.3.1. p1 The operand of the increment or decrement prefix operator must be atomic or unqualified, real or pointer type, and must be a modifiable value of l.

Therefore you can do:

 p_Buf = ( uint8_t* )p_Buf + 1 ; 

Where p_Buf is an lvalue, and ( uint8_t* )p_Buf is the value of r.


Let me note that in your second example you are not using (as you said), but you are declaring a uint8_t pointer. Then, when you use ++ on it, you do not perform any casts (because it is of the correct type), and the operation is valid.

+5
source

Incrementing the void pointer in C is a bad idea. Most compilers do not even allow you to compile it. Use this instead:

 p_Buf = (uint8_t*)p_Buf + 1; 
+1
source

The @ 2501 answer posted is absolutely correct, but does not explain why the standard requires an lvalue for post-increment. The main reason is that you need an lvalue (variable or memory location) for the post-increment in order to increment it.

When you apply p_Buf to the uint8_t* type, you created an rvalue in C. In simple terms, rvalues ​​represent transient values ​​that can be passed to functions assigned to variables, etc. Post-increment returns the original value, and then updates the variable or memory cell in which the value was stored, increasing it. Because they exist only during expression, rvalues ​​cannot be updated, and post-increment cannot work on them. So the problem with

  otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 

is that ((uint8_t *)pBuf) is just an rvalue expression with no actual storage location. In fact, cast means that you only use the p_Buf value and no longer use the p_Buf variable p_Buf .

On the other hand, when you assign a cast to a variable:

 p_Buf_8bit = (uint8_t *) p_Buf; 

then the variable p_Buf_8bit is the value of l, which is a variable or memory cell. This can be post-incremented, which makes the statement in C quite correct:

  otherFunc (p_Buf_8bit++); 
+1
source

The result of the cast operation is an rvalue, not an lvalue. ((uint8_t *)p_Buf)++ is simply not legal C code.

0
source

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


All Articles