I have a question about lvalue and rvalue:
void * p;
typedef struct
{
int a;
int b;
} TypeA;
&(TypeA*)p; // here it complains lvalue required as unary '&' operand
why the (TypeA*)p gives a rvaule?
p is an object of type "pointer to void"; if you cast the value in p to type "pointer to TypeA" you no longer have an 'object': you have just a 'value'.
'Values' (like 42) have no address.
/* wrong code; this does not work */
int *p = &42; /* values do not */
void *q = &(0xDEADBEEF); /* have addresses */
Casting returns r-value and unary & needs a l-value as its operand.
Address-of Operator: &
The operand of the address-of operator can be either a function designator or an l-value that designates an object that is not a bit field and is not declared with the register storage-class specifier.
(TypeA*)p
This statement is going to type cast and return a value that needs to be assigned to a variable. so you can not directly use & on it since the return is a value which will not have a adress.
Related
why im getting errors in the code given below....
#include <stdio.h>
void foo(int*);
int main()
{
int i = 10;
foo((&i)++);(in this line error shows like this) //error: lvalue required as increment operand
}
void foo(int *p)
{
printf("%d\n", *p);
}
From Member access operators:
The address-of operator produces the non-lvalue address of its operand, suitable for initializing a pointer to the type of the operand.
And from Increment/decrement operators:
The operand expr of both prefix and postfix increment or decrement must be a modifiable lvalue of integer type (including _Bool and enums), real floating type, or a pointer type.
Simply put the & operator does not produce an appropriate object for the ++ operator.
In unqlite c library I found following code:
pObj = jx9VmReserveMemObj(&(*pVm),&nIdx);
where pVm is:
typedef struct jx9_vm jx9_vm;
jx9_vm *pVm
and function called is declared as:
jx9_value * jx9VmReserveMemObj(jx9_vm *, sxu32 *);
What for construct &(*pVm) is used in call instead of just pVm? Is &(*pVm) equivalent to pVm?
Quoting C11, chapter §6.5.3.2, Address and indirection operators
[...] If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and the result is not an lvalue. [...]
So, yes, they are equivalent.
This construct can be used, however, to check the type of the argument against a pointer type. From the property of unary * operator,
The operand of the unary * operator shall have pointer type.
So, the construct &(*pVm)
will be fine, if pvm is a pointer or array name.
will generate compiler error, if pvm is a non-pointer type variable.
See the other answer by Alter Mann for code-wise example.
One more difference (in general) is, pVm can be assigned (can be used as LHS of the assignment operator), but &(*pVm) cannot.
Is &(*pVm) equivalent to pVm?
Yes. *1
Same for *(&pVm).
(*1)
As the *-operator (de-referencing) only is applicable to pointers, the former construct only works on a pointer (or an array, which would decay to a pointer to its 1st element). The latter can be applied to any type of variable.:
Yes, they are the same, but notice that it fails when the object is not an array or a pointer:
#include <stdio.h>
struct t {
int value;
};
typedef struct t t;
int func(t *ptr)
{
return ptr->value;
}
int main(void)
{
t o = {.value = 0};
t v[2] = {{.value = 1}, {.value = 2}};
printf("%d\n", func(&(*o))); /* error: invalid type argument of unary ‘*’ */
printf("%d\n", func(&(*v))); /* WORKS */
return 0;
}
This:
bit_is_set(optos(),opt)
expanding macro bit_is_set:
((*(volatile uint8_t *)(((uint16_t) &(optos())))) & (1 << (opt)))
is not working, with error message: lvalue required as unary '&' operand.
But this:
uint8_t a=optos();
bit_is_set(a,opt)
works fine.
Why?
How do I use the address operator "&" with function returns?
For the same reason why this won't work:
uint8_t optos() {
return 4;
}
int main(void) {
uint8_t* addr = &optos();
return 0;
}
error: lvalue required as unary ‘&’ operand
The & operand requires an lvalue to return an address. A temporary rvalue (in your case the value returned from optos()) can't have its address taken and needs to be bound to a lvalue first.
I am confused about working of the below statement:
*ptr++->str
First ++ operator is applied to ptr which returns rvalue. Next operator is -> has to be applied. Doesn't -> operator require lvalue?
Doesnt -> operator require lvalue?
No. See section 6.5.2.3 of the C99 standard:
The first operand of the -> operator shall have type ‘‘pointer to qualified or unqualified
structure’’ or ‘‘pointer to qualified or unqualified union’’, and the second operand shall
name a member of the type pointed to.
...
A postfix expression followed by the -> operator and an identifier designates a member
of a structure or union object. The value is that of the named member of the object to
which the first expression points, and is an lvalue.
And that's all it says on the matter.
This could be a possible definition for the struct.
#include <stdio.h>
struct fuzz {
char *str;
} stuff = {"Hi there!"} ;
struct fuzz *ptr = &stuff;
int main()
{
char ch='#';
printf("Before: p=%p, ch=%c\n", (void*) ptr, ch);
ch = *ptr++->str;
printf("After: p=%p, ch=%c\n", (void*) ptr, ch);
return 0;
}
Output:
Before: p=0x601020, ch=#
After: p=0x601028, ch=H
And the output proves that the pointer expression is an lvalue. Modifyable, if str would not point to a string constant.
In the following code:
/* mylog.c */
#include <stdio.h>
#include <stdlib.h> /* for atoi(3) */
int mylog10(int n)
{
int log = 0;
while (n > 0)
{
log++;
n /= 10;
}
return log;
}
int mylog2(int n)
{
int log = 0;
while (n > 0)
{
log++;
n >>= 1;
}
return log;
}
int main(int argc, const char* argv[])
{
int (*logfunc)(int); /* function pointer */
int n = 0, log;
if (argc > 1)
{
n = atoi(argv[1]);
}
logfunc = &mylog10; /* is unary '&' operator needed? */
log = logfunc(n);
printf("%d\n", log);
return 0;
}
in the line
logfunc = &mylog10;
I've noticed that the unary & (address of) operator is optional, and the program compiles and runs the same way either with or without it (in Linux with GCC 4.2.4). Why? Is this a compiler-specific issue, or perhaps two different language standards being accepted by the compiler? Thanks.
You are correct that the & is optional. Functions, like arrays, can be automatically converted into pointers. It's neither compiler-specific nor the result of different language standards. From the standard, Section 6.3.2.1, paragraph 4:
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
Operator & is indeed optional when taking the address of a function in your context (assigning it to something). It is not compiler-specific, it follows from the formal definition of the language.
Symmetrically, operator * is optional when invoking the function through a pointer. In your example, you could invoke the function as either (*logfunc)(n) or logfunc(n). You used the latter, but the former would work as well.
Answering in C++. For C the same holds
Quote from the C++ standard (4.3.1):
An lvalue of function type T can be
converted to an rvalue of type
“pointer to T.” The result is a
pointer to the function.50)
The same for arrays. (4.2.1)
An lvalue or rvalue of type “array ofN
T” or “array of unknown bound of T”
can be converted to an rvalue of type
“pointer to T.” The result is a
pointer to the first element of the
array.
But please DO note that these are conversions and by no means is a function a function-pointer or is an array a pointer. HTH
From the standard (6.3.2.1/4) :
A function designator is an expression
that has function type. Except when it
is the operand of the sizeof
operator or the unary & operator, a
function designator with type
‘‘function returning type’’ is
converted to an expression that has
type ‘‘pointer to function returning
type’’.
So yes, omitting the & yields a pointer to function anyway.