Why isn't function call an lvalue - c

This should be pretty obvious, but I could not any normative reference in the Standard explicitly that function call is (not) an lvalue. There is somewhat related question, but it's about C++ and no references is provided.
Looking through 6.5.2.2(p5) Function calls the only I could find is
If the expression that denotes the called function has type pointer to
function returning an object type, the function call expression has the
same type as that object type, and has the value determined as
specified in 6.8.6.4
6.3.2.1(p1) states that
An lvalue is an expression (with an object type other
thanvoid) that potentiallydesignates an object
So I tried to find if a function call designates an object. It is not specified in the Standard if the function call result has storage duration and lifetime. Since any object has storage duration and lifetime I concluded that any function call expression does not designate an object an hence not an lvalue.
But this seems confusing and complicated. In particular I found an example 6.5.2.3(p7):
EXAMPLE 1 If f is a function returning a structure or union, and x is
a member of that structure or union, f().x is a valid postfix
expression but is not an lvalue.
Judging by this example if f() would be an lvalue f().x would also be an lvalue. But examples are informative which made me confused.

It's not an lvalue because its described as a "value" in the paragraph you quoted. The standard explicitly mentions when an expression has the property of being an lvalue. For instance:
6.5.3.2 Address and indirection operators (emphasis mine)
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.
As for accessing a union or member. The standard doesn't require the postfix expression in expr.id to be an lvalue. On the contrary. The whole member access has the same value category as the postfix expression:
6.5.2.3 Structure and union members (emphasis mine)
3 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, and is an lvalue if the first expression is
an lvalue. If the first expression has qualified type, the result
has the so-qualified version of the type of the designated member.
So in the example you quoted, f().x is a value, and not an lvalue, because f() itself is not an lvalue.

The return value of a function is not an lvalue as the Standard defines the term, but there are contexts where it would offer the semantics of one.
Given any structure type:
struct foo {...whatever... };
one can write a function whose return value can be used in ways that would require an lvalue of type struct foo [most typically passing the address of such an lvalue to another function].
struct wrapped_foo {struct foo it[1];} wrap_foo(foo it)
{
struct wrapped_foo ret = {it};
return ret;
}
extern void do_something(int,int,int,struct foo const *p,int,int,int);
void demo_of_passing_address_of_a_foo(struct foo x)
{
do_something(1,2,3,&(wrap_foo(x).it[0]),4,5,6);
}
Note that while the return value of wrap_foo(x) isn't an lvalue, wrap_foo(x).it[0] is one, and its address can be taken. The lifetime of the object identified thereby will extend through the evaluation of the enclosing expression, i.e. the call to do_something. If the subscripting operator were defined in its own right as an operator which does not result in array-to-pointer decomposition but simply yields a value of the element type, which would be an lvalue only when the array was one, then wrap_foo(x).it[0] would not be an lvalue, and issues of lifetime would be irrelevant.
While the ability to pass the address of a temporary is useful, it adds compiler complexity by requiring that a compiler given something like the above allocate space for wrap_foo's return value before stacking any of the arguments to the outer function call. If such compiler complexity is required, it could just as well allow such semantics to be achieved by allowing top-level argument expressions to use & on values of arbitrary type (yielding a const-qualified pointer to an object whose lifetime would be that of the outer enclosing expression).

Related

Can you proof why casting is important when I deference a void pointer?

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.

Is the meaning of l-value different in c and c++?

I was told that the array name is an non-modifiable l-value in C, but it is still confusing.
Someone said that the array name can not be placed on the left side of the formula because it is converted to a pointer that is not l-value.
My question is Here:
is an array name l-value?
Is there any difference between what means l-value in c and c++?
is an array name l-value?
Yes, in both C and C++.
Is there any difference between what means l-value in c and c++?
Yes, but not of great significance. Here is the definition from C11, paragraph 6.3.2.1/1:
An lvalue is an expression (with an object type other than void) that potentially designates an object
C also includes a footnote (#64) expanding on that, which includes:
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''. [...] An
obvious example of an lvalue is an identifier of an object.
Here is the definition from C++14, paragraph 3.10/1:
An lvalue (so called, historically, because lvalues could appear on
the left-hand side of an assignment expression) designates a function
or an object.
If you read carefully, you will notice that in C, an lvalue only potentially designates an object, whereas in C++, no room is left for unfulfilled potential -- an lvalue does designate an object or function. You'll also then notice that C++ includes function designators among its lvalues, whereas C does not. In practice, these distinctions are more technical than deeply meaningful. And neither of them affects the answer to your question (1).
You'll also note that neither definition is written in terms of how or where an lvalue can be used. That follows from the definition and other specifications; it is not a defining characteristic.
In both C and C++, an array's identifier designates an object -- the array -- and it is therefore an lvalue. Whether such an lvalue may in fact appear as the left operand in an assignment expression is an entirely separate question.
In the context of C:
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.
2 Except when it is the operand of the sizeof operator, the _Alignof 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. If the lvalue has qualified type, the value has the unqualified version of the
type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic
version of the type of the lvalue; otherwise, the value has the type of the lvalue. If the
lvalue has an incomplete type and does not have array type, the behavior is undefined. If
the lvalue designates an object of automatic storage duration that could have been
declared with the register storage class (never had its address taken), and that object
is uninitialized (not declared with an initializer and no assignment to it has been
performed prior to use), the behavior is undefined.
3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. If the array object has
register storage class, 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.
C 2011 Online Draft
Summarizing:
An array expression (that is, any expression of array type) is indeed an lvalue; however, unless it is the operand of the sizeof, _Alignof, or unary & operators, that expression gets converted ("decays") to an expression of pointer type whose value is the address of the first element of the array, and that converted pointer expression is not an lvalue, and thus cannot be the target of an assignment.
That is, if you declare a as
T a[N]; // for any type `T`
then the expression a has type "N-element array of T". If a is not the operand of the sizeof, unary &, or _Alignof operators, it will be converted to an expression of type "pointer to T", and its value will be the same as &a[0], and that value cannot be the target of an assignment (it's logically the same as writing 2 = 3 - you're trying to assign a value to a value, not an object, which doesn't work).

Does array subscription count as taking address of object?

This question is inspired by answers to this question.
Following code has potential for undefined behaviour:
uint64_t arr[1]; // Uninitialized
if(arr[0] == 0) {
C standard specifies that uninitialized variable with automatic storage duration has indeterminate value, which is either unspecified or trap representation. It also specifies that uintN_t types have no padding bits, and size and range of values are well defined; so trap representation for uint64_t is not possible.
So I conclude that uninitialized value itself is not undefined behavior. What about reading it?
6.3.2.1 Lvalues, arrays, and function designators
...
Except when it is the operand of the sizeof operator, the _Alignof 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. ... -- irrelevant text removed --
... If
the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. If the array object has
register storage class, the behavior is undefined.
Question: Does subscripting array count as taking the address of an object?
Following text seems to imply that subscripting array requires conversion to a pointer, which seems impossible to do without taking address:
6.5.2.1 Array subscripting
Constraints
One of the expressions shall have type ‘‘pointer to complete object type’’, the other
expression shall have integer type, and the result has type ‘‘type’’.
Semantics
A postfix expression followed by an expression in square brackets [] is a subscripted
designation of an element of an array object. The definition of the subscript operator []
is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that
apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the
initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).
This makes §6.3.2.1 paragraph 3 seem weird. How could array have register storage class at all, if subscription requires conversion to a pointer?
Yes, array subscripting counts as taking the address, as per the part you quoted in 6.5.2.1. The expression E1 must have its address taken.
Therefore the special case of UB in 6.3.2.1 does not apply to array indexing. If array indices are used, it is not relevant if the array could be stored with register storage duration or not (a variable having its address taken cannot use register storage duration).
You are correct in assuming that reading an uninitialized stdint.h type with indeterminate value, which has its address taken, does not invoke undefined behavior (guaranteed by C11 7.20.1.1), but merely unspecified behavior. The value could be anything and it can be non-deterministic between several reads, but it cannot be a trap.
"Reading an uninitalized variable is always UB" is a wide-spread but incorrect myth.
Further information with normative sources in this answer.

Is it undefined in C11 to modify the result of a function call, or access it after the next sequence point?

At C99§6.5.2.2p5 there's this little gem, bolded by me for the purpose of emphasizing the question:
If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void. If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined.
This allowed us to return structs, for example:
struct foo { int foo;
char bar[2]; };
struct foo get_foo() {
struct foo return_value = { .foo = 42,
.bar = "x" };
return return_value;
}
... and assign that return value somewhere else from within the caller, for example:
int main(void) {
struct foo bar = get_foo(); /* Well defined because the return value
* is copied -before- the sequence point
* that terminates its storage duration */
printf("%s\n", bar.bar);
printf("%d\n", get_foo().foo); /* Again, well defined because the access
* occurs before the next sequence point
* (the function call). */
}
... whilst rendering examples like the following invalid:
int main(void) {
printf("%s\n", get_foo().bar); /* UB because there's a sequence point
* between the evaluation of the sub-
* expression `get_foo().bar` and the
* entrace to the function `printf` */
get_foo().bar[0]++; /* UB because an attempt is made to modify the
* result of a function call */
}
--
C11§6.5.2.2p5, however, is essentially the same paragraph but without the bolded text.
If the expression that denotes the called function has type pointer to function returning an object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void.
Are those examples above that are undefined behaviour in C99 still undefined in C11? If so, which paragraphs invalidate them? If not, I gather there must be some extension of the storage duration of automatic values/objects returned; which section of the standard specifies that extension of storage duration?
Are those examples above that are undefined behaviour in C99 still undefined in C11?
The examples posed above that are well defined are still well defined.
The temporary lifetime of the object in this one "ends when the evaluation of the containing full expression or declarator ends", so this previously undefined example is now well defined:
printf("%s\n", get_foo().bar);
This example is still undefined behaviour, because an attempt is made to modify an object that has temporary lifetime:
get_foo().bar[0]++;
If so, which paragraphs invalidate them? If not, I gather there must be some extension of the storage duration of automatic values/objects returned; which section of the standard specifies that extension of storage duration?
As pointed out by Jens Gustedt in a comment, C11§6.2.4p8 seems to convey a slightly different meaning to the sentence that C99§6.5.2.2p5 contains which C11§6.5.2.2p5 omitted:
A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime.36) Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression or full declarator ends. Any attempt to modify an object with temporary lifetime results in undefined behavior.
36) The address of such an object is taken implicitly when an array member is accessed.
It seems that a little reorganisation was performed; the "storage duration extension" sentence in C99 was changed and moved from the "function call" section to the "storage duration" section, where it fits better.
The only question remaining is whether or not the result of a function call is considered an lvalue. For every operator that produces an lvalue, it seems as though it is explicitly mentioned that the operator produces an lvalue. For example, C11§6.5.3.2p6 states that the unary * operator produces an lvalue providing its operand points at an object.
The function call operator, however, says nothing about producing an lvalue, so we must assume that it doesn't produce an lvalue. If that's not good enough, then consider C11§6.5.2.3p3 and p7, which say:
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,95) and is an lvalue if the first expression is an lvalue.
If f is a function returning a structure or union, and x is a member of that structure or union, f().x is a valid postfix expression but is not an lvalue.
We can also deduce from these two paragraphs that the result of a function is not an lvalue, thus meeting the criteria for C11§6.2.4p8 (quoted above).
Footnote 95 is interesting but tangential to the discussion on hand:
95) If the member used to read the contents of a union object is not the same as the member last used to
store a value in the object, the appropriate part of the object representation of the value is reinterpreted
as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type
punning’’). This might be a trap representation.

lvalue required

what does the error message "Lvalue required" actually mean?
An lvalue is something that can appear on the left side of an assignment, in other words 'something that can be assigned'
So, look for an assignment where the left hand side isn't 'assignable', for example, something as simple as this might trigger such an error
if (0 = foo)
{
}
Here you've got an attempt to assign to a constant because of accidentally using = rather than ==
See also
often used seldom defined terms: lvalue
lvalue and rvalue
“l-value required” error
It means the implementation expects an object, but you just passed a value or function. This happens for assignments you passed a non-lvalue or for address-of operations applied to non-functions.
Lvalue stands for "location value" and means an expression that refers to an object either declared as register or to a memory location. Something like 42 is a value that matches neither criteria. More formally there are three categories
Lvalues: Referring to objects. This includes objects declared const. Such are non-modifiable lvalues.
Function designators: Referring to functions. printf is a function designator, but &printf is not, while *&printf is again.
Others: Sometimes called "rvalue" and by the Standard described as "the value of an expression". Examples are var + 0 (yielding a value not associated with objects anymore), or an enumerator of an enumeration. &printf belongs to this category.
The C99 standard states (6.3.2.1):
An lvalue is an expression with an object type or an incomplete type other than void; 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.
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".
In other words, an lvalue is something that you can locate for potentially changing. A modifiable lvalue is one that you're actually allowed to change.
For example, the C statement:
x = 7;
is valid because x is an lvalue. On the other hand, the statement:
14 = 7;
is not valid because 14 is not something you can locate for an assignment.
The snippet:
const int x = 7;
actually creates an lvalue called x even though you're not permitted to change it (it's not a modifiable `lvalue).
the error cometh if you code somrthing like function(parameter) = value; because you cannot assign value to anything that is not a possible container for it.
Most likely it means that you tried to assign a value to something that cannot be assigned to. For example, both of the following would probably cause that error:
5 = 5;
myObject->myMethod() = 5;

Resources