简体   繁体   中英

Is typecasting on lvalue of operation not allowed?

I have the below code, where i am doing a type cast of integer pointer to void pointer and try to assign char address.

void main()
{
   int *ptr;
   char a = 10;
   (void *)ptr = &a;
   printf("%d\n", *ptr);
}

I am getting below error, Is there anyway that i can fix this?

error: lvalue required as left operand of assignment
    (void *)ptr = &a;

Yes, you cannot cast the left operand of the assignment operator in C.

Also, in your case you could just do it the other way to make your code work:

void main()
{
   int *ptr;
   char a = 10;
   ptr = (int*) &a; // this is perfectly fine
   printf("%d\n", *ptr);
}

The cast on lvalue is valid, ie, (void *)ptr itself is valid, but it's not an lvalue anymore. This is called lvalue conversion .

The fix, as @Joachim commented:

ptr = (int *) &a;
ptr = (int *)&a ;

is more natural but it's not portable. Might give the impression it works on little endian machine (most nowadays) but relies on byte after &a being null. Which it's not the case.

I would suggest

printf("%d\n", (int)a) ;

type cast of of a variable or expression results in r-value. so (void *)ptr gives r-value and you are trying to allocate &a to r-value. it is something like 0x12345=&a which is wrong so you are getting l-value is required.

The question doesn't match your example - but the answer to your question (instead of your example) - is yes - you can. Here's how:

void encode_fixed32(char *buffer,float input) {
  ((float *)buffer)[0]=input;
}

void decode_fixed32(char *buffer) {
  return ((float *)buffer)[0];
}

EDIT : this answer only works in C++, not C, but might be relevant nevertheless.

You have to cast your lvalue to a reference-to-a-pointer instead of a pointer, and then the assignment will work:

void main()
{
   int *ptr;
   char a = 10;
   (void *&)ptr = &a;
   printf("%d\n", *ptr);
}

Note the & after void * . This way you preserve its lvalue-ness and you can assign into it.

However, in this particular case the printf behaviour will still be undefined because you are reinterpreting a char as an int, and even if you assume little endian, you may still have 3 undefined bytes after the byte representing 10 .

A better use case:

int a[5];
int *ptr = a + 2; // points to the element with index=2
(char *&)ptr += sizeof(int); // advances the pointer to the next element

This is useful eg when you are doing a strided for-loop over an array in CUDA or on an embedded device, and you want to cache the exact step in advance to avoid multiplication by 4 every time inside the loop:

const int stride = sizeof(int)*step;
int *my_ptr = first_ptr;
for (int i = 0; i < count; ++i) {
    ...
    (char *&)my_ptr += stride;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM