I have some problem with my code.
There are the following functions:
static Poly PolyFromCoeff(int coeff);
static Mono MonoFromPoly(const Poly *p, int exp);
And in another function I have this line:
Mono m = MonoFromPoly(&PolyFromCoeff(10),4);
But I receive this error message:
lvalue required as unary ‘&’ operand
If I save the first result to a variable, there is no error:
Poly p = PolyFromCoeff(10);
Mono m = MonoFromPoly(&p,4);
Why is the first solution wrong?
As it says, operator & requires a lvalue as its argument, i.e. it cannot be applied to temporary values. Addresses are not associated with values, with objects only.
In the second form you instantiate an object that holds this value and you can easily take the address of that object.
The C language expressly prohibits you from taking the address of a rvalue (which is what a function returns). This clause from the C11 standard (committee draft) sums it up:
6.5.3.2 Address and indirection operators
Constraints
The operand of the unary & operator shall be either a function designator, the result of a
[] or unary * operator, or an lvalue that designates an object that is not a bit-field and is
not declared with the register storage-class specifier.
If you are confused about lvalue and rvalue, think of it like this:
lvalue is something that has an identifier and storage
rvalue is a temporary result or literal value
If you have a C++ background, you might have been confused because the behavior of references is different. In C++, it's okay to have this:
static Poly PolyFromCoeff(int coeff);
static Mono MonoFromPoly(const Poly &p, int exp);
Mono m = MonoFromPoly( PolyFromCoeff(10), 4 );
Related
Why is necessary do casting when I dereference a void pointer?
I have this example:
int x;
void* px = &x;
*px = 9;
Can you proof why this don't work?
By definition, a void pointer points to an I'm-not-sure-what-type-of-object.
By definition, when you use the unary * operator to access the object pointed to by a pointer, you must know (well, the compiler must know) what the type of the object is.
So we have just proved that we cannot directly dereference a void pointer using *; we must always explicitly cast the void pointer to some actual object pointer type first.
Now, in many people's minds, the "obvious" answer to "what type does/should a 'generic' pointer point to?" is "char". And, once upon a time, before the void type had been invented, character pointers were routinely used as "generic" pointers. So some compilers (including, notably, gcc) extend things a bit and let you do more (such as pointer arithmetic) with a void pointer than the standard requires.
So that might explain how code like that in your question might be able to "work". (In your case, though, since the pointed-to type was actually int, not char, if it "worked" it was only because you were on a little-endian machine.)
...And with that said, I find that the code in your question does not work for me, not even under gcc. It first gives me a non-fatal warning:
warning: dereferencing ‘void *’ pointer
But then it changes its mind and decides this is an error instead:
error: invalid use of void expression
A second compiler I tried said something similar:
error: incomplete type 'void' is not assignable
Addendum: To say a little more about why the pointed-to type is reuired when you dereference a pointer:
When you access a pointer using *, the compiler is going to emit code to fetch from (or maybe store to) the pointed-to location. But the compiler is going to have to emit code that accesses a certain number of bytes, and in many cases it may matter how those byte(s) are interpreted. Both the number and the interpretation of the bytes is determined by the type (that's what types are for), which is precisely why an actual, non-void type is required.
One of the best ways I know of appreciating this requirement is to consider code like
*p + 1
or, even better
*p += 1
If p points to a char, the compiler is probably going to emit some kind of an addb ("add byte") instruction.
If p points to an int, the compiler is going to emit an ordinary add instruction.
If p points to a float or double, the compiler is going to emit a floating-point addition instruction. And so on.
But if p is a void *, the compiler has no idea what to do. It complains (in the form of an error message) not just because the C standard says you can't dereference a void pointer, but more importantly, because the compiler simply doesn't know what to do with your code.
In short:
The target of an assignment expression must be a modifiable lvalue, which cannot be a void expression. This is because the void type does not represent any values - it denotes an absence of a value. You cannot create an object of type void.
If the expression px has type void *, then the expression *px has type void. Attempting to assign to *px is a constraint violation and the compiler is required to yell at you for it.
If you want to assign a new value to x through px, then you have to cast px to an int * before dereferencing:
*((int *)px) = 5;
Chapter and verse:
6.2.5 Types
...
19 The void type comprises an empty set of values; it is an incomplete object type that
cannot be completed.
...
6.3.2.1 Lvalues, arrays, and function designators
1 An lvalue is an expression (with an object type other than void) that potentially
designates an object;64) if an lvalue does not designate an object when it is evaluated, the
behavior is undefined. When an object is said to have a particular type, the type is
specified by the lvalue used to designate the object. A modifiable lvalue is an lvalue that
does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including,
recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
...
6.3.2.2 void
1 The (nonexistent) value of a void expression (an expression that has type void) shall not
be used in any way, and implicit or explicit conversions (except to void) shall not be
applied to such an expression. If an expression of any other type is evaluated as a void
expression, its value or designator is discarded. (A void expression is evaluated for its
side effects.)
...
6.3.2.3 Pointers
1 A pointer to void may be converted to or from a pointer to any object type. A pointer to
any object type may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer.
...
6.5.3.2 Address and indirection operators
...
4 The unary * operator denotes indirection. If the operand points to a function, the result is
a function designator; if it points to an object, the result is an lvalue designating the
object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an
invalid value has been assigned to the pointer, the behavior of the unary * operator is
undefined.102)
...
6.5.16 Assignment operators
...
Constraints
2 An assignment operator shall have a modifiable lvalue as its left operand.
More specifically, dereferencing a void pointer violates the wording of 6.5.3.2 Address and indirection operators, paragraph 4:
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ''pointer to type'', the result has type ''type''. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
Since a pointer to void has no "type" - it can't be dereferenced. Note that this is beyond undefined behavior - it is a violation of the C language standard.
It probably doesn't work because it violates a rule in the ISO C standard which requires a diagnostic, and (I'm guessing) your compiler is treating that as a fatal situation.
According to ISO C99, as well as the C11 Draft (n1548), the only constraint on the use of the * dereferencing operator is "[t]he operand of the unary *operator shall have pointer type." [6.5.3.2¶2, n1548] The code we have here meets that constraint, and has no syntax error. Therefore no diagnostic is required for the use of the * operator.
However, what is the meaning of the * operator applied to a void * pointer?
"The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. [6.5.3.2¶4, n1548]
The type void is neither a function nor an object type, so the middle sentence, which talks about producing a function or object designator, is not applicable to our case. The last sentence quoted above is applicable; it gives a requirement that an expression which dereferences a void * has void type.
Thus *px = 9; runs aground because it's assigning an int value to a void expression. An assignment requires an lvalue expression of object type; void is not an object type and the expression is certainly not an lvalue. The exact wording of the constraint is: "An assignment operator shall have a modifiable lvalue as its left operand." [6.5.16¶2, n1548] Violation of this constraint requires a diagnostic.
It appears from my perhaps naive reading of the standard that the expression *px as such is valid; only no attempt must be made to extract a result from it, or use it as the target of an assignment. If that is true, it could be used as an expression statement whose value is discarded: if (foo()) { *px; }, and it could be redundantly cast to void also: (void) *px. These apparently pointless situations might be somehow exploited by, or at least arise in, certain kinds of macros.
For instance, if we want to be sure that the argument of some macro is a pointer we can take advantage of the constraint that * requires a pointer operand:
#define MAC(NUM, PTR) ( ... (void) *(PTR) ...)
I.e. somewhere in the macro we dereference the pointer and throw away the result, which will diagnose if PTR isn't a pointer. It looks like ISO C allows this usage even if PTR is a void *, which is arguably useful.
I'm trying to figure out how C determines if an expression is a valid LVALUE.
I know declaring variable gives it a named memory space, which is variable name. The variable name can be RVALUE or LVALUE. If used to represent a value its content is used, but if it is used as LVALUE its address is used to tell that the expression at right side is stored in this address. The picture I see for this operation is like ADDRESS=VALUE: That's how the right and left expressions for assignment operator are evaluated.
So why I can't define a variable like int a;, and then use the address of operator to store value in that address, like &a = 5;?
I know &a returns a constant pointer, but that means I can't change the address or I can't change the value stored in the address? If its content can't be changed, then why using *&a=5 works?
Why I can't assign a value this way, although the left hand expression is always evaluated to an address as I understand? Maybe something is wrong in my understanding?
Automatic lvalue conversion
This is covered by C 2018 6.3.2.1 2, which says:
Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion.…
Consider the expression x = y + z:
y is an operand of +. The + operator is not in the list of exceptions above. So y is converted to its value.
z is an operand of +. The + operator is not in the list of exceptions above. So z is converted to its value.
x is the left operand of =, which is the assignment operator. That is in the list of exceptions above. So x remains an lvalue.
About &a = 5
In regard to int a; followed by &a = 5;:
The result of the & operator is merely an address—it is just a value; there is no object holding this value, so it is not an lvalue.
The assignment operator must have an lvalue as its left operand. C 2018 6.5.16 2 is a constraint that says “An assignment operator shall have a modifiable lvalue as its left operand.”
Therefore &a = 5; violates a constraint, and a C compiler is required to produce a diagnostic message for it. The = operator cannot have a plain value as its left operand.
It is possible to design a programming language so that the assignment operator accepts &a = 5; and uses it to store the value on the right in the location given on the left. The BLISS language does this. In BLISS, the name of a variable always provides its address. To get the value, you must prefix the variable with a period (which acts like C’s unary * operator). So you would write z = .x + .y. So the fact that C does not do this is a choice about aesthetics and convenience, not about logical necessity. In C, lvalues are automatically converted to values in most places, and the exceptions are for operators that act on objects instead of values. In BLISS, you must explicitly designate each lvalue-to-value conversion.
About *a = 5
In *&a=5:
The * operator produces an lvalue, per C 2018 6.5.3.2 4: “The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object.…”
Thus *&a provides the lvalue that the assignment operator requires.
First of all, C does not use the term rvalue, preferring the term "value of an expression". The term lvalue is used, and it means (C11 6.3.2.1p1)
[...] an expression (with an object type other than void) that potentially designates an object)
It does not mean the address of the object, it means that the lvalue is the object.
The operand of & more often than not is an lvalue too
The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
The result is a value of an expression of a pointer type, an address. Even though an address points to an object, it is not the object. Just like 1600 Pennsylvania Avenue NW in Washington, D.C. is an address, but it is not the building found at that address.
So if you have a house:
house my_House;
you can ask for its address
&my_house;
which is the address of your house, but it is not a house, i.e. not an lvalue, but the house located at the address of your house is a house, i.e. an lvalue:
*&my_house;
In the Standard N1570, Section 6.5.3.2#3 the following is specified (emp. mine):
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.
Later on the section 6.5.3.2#4 specifies:
If the operand points to a function, the result is a function
designator; if it points to an object, the result is an lvalue
designating the object.
This two sections look contradictory to me. The first on I cited specifies that the result is not an lvalue, but the second one specifies that the result of indirection operator is an lvalue.
Can you please explain this? Does it mean that in case of object the operators * and & does not eliminate each other?
Section 6.5.3.2#3 talks about the unary & operator and the 6.5.3.2#4 talks about the unary * operator. They have different behaviors.
Elaboration (from comment):
The point is that unary & does not result in an lvalue, even in the case where it is considered omitted because it immediately precedes unary * in a dereference context. Just because both operators are considered omitted doesn't change the fact the resulting expression is not an lvalue; the same way it would not be if a solo unary & were applied.
int a;
&a = ...;
is not legal (obviously). But neither is
int a;
&*a = ...;
Just because they are considered omitted doesn't mean &* is lvalue-equivalent to solo a.
This question already has answers here:
Using & (addressof) with const variables in C
(3 answers)
Closed 5 years ago.
According to The C programming language by Kernighan and Ritchie, page 94
& operator cannot be applied to constants
const int u = 9;
printf ("\nHello World! %u ", &u);
So, why does that work?
You are misunderstanding between constant and const. Both are different things in C language.
& operator cannot be applied to constants
In C programming, It means you cannot use &(address operator) on the literal constant to get the address of the literal constant.
For examples :
&10
or
&('a')
If you use & operator over literal constant, the compiler will give an error because constant entity does not have corresponding address.
According to the Draft Standard §6.5.3.2 ¶1, use of the address operator must obey the following constraint:
The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
The meaning of lvalue is given in §6.3.2.1 ¶1:
An lvalue is an expression (with an object type other than void) that potentially designates an object.
According to §3.15 ¶1 an object is a:
region of data storage in the execution environment, the contents of which can represent values.
Now, a constant is not an lvalue; a constant has a value, but a constant does not indicate an object, and a value can't be assigned to a constant.
So, a constant is not a function designator, is not the result of a [] or unary * operator, and is not an lvalue, which means that taking the address of a constant is a constraint violation. A diagnostic message must be issued by a conforming implementation.
On the other hand, given const int u = 9;, u is a const qualified variable of type int. This declaration does reserve storage for the variable, and u is an lvalue. The use of const does not indicate that u is a constant, but that the object indicated by the identifier u is const (which is not the same thing). It may be better to think of const qualified variables as "read-only"; this is a promise made by the program that the object indicated by u will not be modified. Since u is an lvalue here (that is not a bit-field, and is not declared with the register keyword), it is fine to take its address with &u.
Do note that the posted code has undefined behavior, since the correct printf() conversion specifier for printing addresses is %p; its argument must be cast to (void *). Mismatched conversion specifiers and arguments lead to undefined behavior. So, the correct code would be:
const int u = 9;
printf ("\nHello World! %p ", (void *) &u);
No, in order to get variable's address in the memory, we can apply pointer to any of them, coz CPU allocates memory for all of them. On the other hand this question has already been asked.
The term "constant" in C indeed means only literal constants, like 2, for example. A const-qualified object is not a "constant" in C terminology
Link to question
I have two functions:
void a(int * p);
int b();
Is it possible to pass the address of the return value of function b to function a something like this: a(&b()) ?
A compound literal seems to do the trick (requires a C99 compiler):
int a()
{
return 5;
}
void b(int *a)
{
// do something with a
printf("%d\n", *a);
}
int main(void)
{
b(&(int){ a() });
}
Output is 5.
Only by using a temporary variable:
int result = b();
a(&result);
EDIT: Apparently there's also a way to do this using a compound literal, described in another answer here.
Nope - what would be the address of that return value? You need to store the return value in a variable, then pass the address of that variable in.
No. C11 says that (emphasis mine):
6.5.3.2.1
The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
Now it clearly isn't a function, a [] or a unary *. Let's see what is an lvalue:
6.3.2.1
An lvalue is an expression (with an object type other than void) that potentially
designates an object;64) if an lvalue does not designate an object when it is evaluated, the
behavior is undefined. ...
64) The name ‘‘lvalue’’ comes originally from the assignment expression E1 = E2, in which the left
operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an
object ‘‘locator value’’. What is sometimes called ‘‘rvalue’’ is in this International Standard described
as the ‘‘value of an expression’’.
An obvious example of an lvalue is an identifier of an object. As a further example, if E is a unary
expression that is a pointer to an object, *E is an lvalue that designates the object to which E points.
So in short, an lvalue designates an object. Since b() doesn't designate a specific object, it is not an lvalue. You can tell this by seeing also that b() = 2; is wrong.
No you can't do that in C. Also note C doesn't have something called as reference as in C++.
For that C has pointers to achieve the same behaviour..
To achieve the same goal in C use temporary variable like,
int val;
val = b();
a( &val ); // & is called as "address of" operator in C
To answer why there is no reference in C, from my understanding pointer and reference are meant to achieve the same goal - minimizing or avoiding data copy. For this C's pointer is good enough, though technically both have some difference in C++ (taken for reference)
You could pass a reference to b() as an argument to a then call b from a:
void a(void (*b)(int)) {
// call b
int local_var = b(<something>);
}