vimal prathap
vimal prathap

Reputation: 531

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;

Upvotes: 2

Views: 3054

Answers (7)

gebjon
gebjon

Reputation: 131

Sorry to be 8 years late to this discussion, but I came across it because I have a similar problem and have found a solution in C. The issue arises because, as others have said, a cast like (void *)ptr does not result in an lvalue so you cannot assign to it. But a dereferenced pointer like *(void **)&ptr is an lvalue. So you could change your code to:

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

and this compiles and runs OK, and does what I think you want it to do. It gives odd output because the value output comes partly from uninitialised bytes adjacent to the char a variable, so it's a dangerous thing to do, but it is valid C.

Modified code compiling and running here

Upvotes: 0

szali
szali

Reputation: 518

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 e.g. 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;
}

Upvotes: 0

user6528451
user6528451

Reputation:

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];
}

Upvotes: 0

Nagi
Nagi

Reputation: 21

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.

Upvotes: 1

marom
marom

Reputation: 5230

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) ;

Upvotes: 4

syntagma
syntagma

Reputation: 24344

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);
}

Upvotes: 3

Yu Hao
Yu Hao

Reputation: 122423

The cast on lvalue is valid, i.e, (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;

Upvotes: 3

Related Questions