Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: lvalue required as unary & operand

Tags:

c++

linux

While compiling (with Linux Server release 6.1)

strftime(AppTime, sizeof(AppTime),"%Y/%m/%d %T", localtime(&((long)u32_Time)));

getting error "error: lvalue required as unary '&' operand"

but the same code compiled successfully with Red Hat Enterprise Linux AS release 3.

Why so? How to correct this?

like image 571
Rahul_cs12 Avatar asked Apr 01 '14 13:04

Rahul_cs12


People also ask

What is lvalue error in C++?

This error occurs when we put constants on left hand side of = operator and variables on right hand side of it. Example: #include <stdio.h>

How do you solve lvalue as left operand of assignment?

lvalue means an assignable value (variable), and in assignment the left value to the = has to be lvalue (pretty clear). Both function results and constants are not assignable ( rvalue s), so they are rvalue s.


2 Answers

The address-operator & requires a variable to take the address from. The result of your cast (long)u32_Time is a temporary that does not necessarily reside in memory and therefore has no address that could be taken. So if that piece of code ever compiled somewhere it was a nonstandard compiler extension.

The standard, §5.3.1,3 demands:

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue [...]

How to fix this: std::localtime expects a pointer to a std::time_t so you best provide that. You did not provide any explanation or further code, so I can only guess that u32_Time is some 4 byte unsigned arithmetic type that is supposed to represent a time in some manner. How that is properly converted into a std::time_t depends on how your compiler implements the latter and how you got the value of the further. Simply applying a C-cast is not portable, and casting to long is even less portable.
If, and only if the std::time_t on your current platform is also a unsigned 32 bit type using the same representation as your u32_Time, it might suffice to use

 localtime(reinterpret_cast<std::time_t*>(&u32_Time));

More portable would be storing the value in the correct data type first:

 std::time_t time = u32_Time;
 localtime(&time);

That way you will get the necessary warnings and/or errors if time_t and the type of u32_Time are not compatible.

I would strongly advice against using C-casts, because once you have to port this piece of code to another platform you will have no means to find that nasty cast easily.

like image 135
Arne Mertz Avatar answered Oct 25 '22 23:10

Arne Mertz


It's probably best to start with what the error means. An "lvalue" is something that appears on the left side of an equals sign. What it means is that your argument to the "address of" operator (&) must be something that you could assign to. In your case, this isn't syntactically correct:

(long)u32_Time = 0;

The reason for this restriction is that the & operator returns the address of something that is stored somewhere. (long)u32_Time isn't stored somewhere, but u32_Time is.

This might have worked ok on more tolerant compilers because it would allocate some space for the long representation of u32_Time and then give you a pointer to that, but I wouldn't count on that working (as can be seen in Linux Server release 6.1).

To fix this, you can just create a new variable and take it's address instead:

long long_Time = (long)u32_Time;
strftime(AppTime, sizeof(AppTime),"%Y/%m/%d %T", localtime(&long_Time));

However, that's still not perfect. localtime expects a time_t pointer, not a long pointer, and while they might be the same on your platform, you'd be better off with:

time_t time_t_Time = (time_t)u32_Time;
strftime(AppTime, sizeof(AppTime),"%Y/%m/%d %T", localtime(&time_t_Time));
like image 33
rkuris Avatar answered Oct 25 '22 21:10

rkuris