In C standard (N2176),
3.19
value
precise meaning of the contents of an object when interpreted as having a specific type
So I thought that the term "value" is only applicable to an object. However, I also think that an expression may be evaluated to a "value" that is not an object, e.g., 1 + 3. What is the definition of the computation result of an expression? Is it a value (the definition of a value should be extended) or some other term?
Related
New to C. So I saw this line of code
system->word[system->index++] = system->next_char;
Is it equivalent to:
system->word[system->index] = system->next_char;
index++;
What is the precedence for post increment? Does it only increment index's value by 1 after all the operations on the line are done executing?
Updating system->index is defined as a side effect that is not sequenced (is not specified to come before or after) the other operations in the statement. The update may occur before, during, or after other operations.
The fact that it is not sequenced is irrelevant as long as it is not used elsewhere in the statement, because, if it is not used elsewhere, then nothing the statement does can be affected by when the update occurs. (Note that, even if the update to system->index in memory is done before the value is used, the compiler is response for ensuring that the pre-update value is used.)
If the object being updated were used elsewhere in the statement in an unsequenced way (that is, no rule specifies which comes first, the update or the other use), then the behavior of the program would not be defined by the C standard.
This is not a consequence of precedence. Precedence determines the structure of how expressions are interpreted, not the sequencing of their operations.
Not.
system->word[system->index++] = system->next_char;
is equivalent to:
system->word[system->index] = system->next_char;
system->index++;
as index is a field on a struct pointed to by system. In case you have also a scalar variable named index you had had no errors but the wrong variable should have been incremented.
As a general rule, all the unary operators evaluate first on the right side of the variable, then the ones on the left (the right side operators have higher precedence thatn left side ones) and evaluate from closest to the operand, to farthest. So the operator closest to the operand evaluates first, then the one next in the right... so until there are no more right operators on the right, then the closest on the left side, and so on until there are no more left operators on the left.
So what happens if we have -x++ ? The ++ is evaluated first to the value of x and a post increment of the variable is schedule to occur, then the one on the left is evaluated, givin as result the value of x before incrementing, changed of sign, and the variable x gets its value incremented (only incremented, no sign change).
Another example: let's compute ++x->field: first of all ->field (the whole thing, the -> arrow and the field name) is considered a right unary operator, given a pointer gets the value in field named field fo structure pointed to by x. This value is incremented (and stored again in x->field) and the returned value is the final incremented one.
Another final example: let's compute *p++. The value of p is scheduled to be post incremented, but it's previous value is retained. Then the old value of p is used to access the value pointed to by it, giving the original pointed to value. Finally p is incremented and points to the value next to the value accessed.
This is a question related to defect report 452 of the C standard. Document N1888 provides further information about the original problem, but I cannot understand why it states the following:
The effective type rule from 6.5.p6 (the rule that describes what is the effective type of an object) does not seem to apply to an object with temporary lifetime resulting from a comma expression. As such, it does not seem to have an effective type. As such, type punning is seemingly allowed:
long func3() {
union u2 o3 = { .x=42 };
return (0, o3).y;
}
My question is what causes type punning to be legal if the object with temporary lifetime created by the expression (0, o3) does not have an effective type? I believe the effective type of that object would be relevant only if one would try to access its stored value using a different type, but I do not see how that is the case here.
I believe the effective type of that object would be relevant only if one would try to access its stored value using a different type, but I do not see how that is the case here.
But indeed the object is tried to access its stored value using a different type.
union u2 {
int x;
long y;
char ca[2];
};
Members x and y have different types (even if they might have the same representation).
But when it comes to unions one cannot say we are accessing one object through the type of the other (I know there is some debate about this, but there is a note in the standard that allows type punning through unions; I know notes are not normative, but I believe the intention was to make it valid).
It appears you are referring to this note in the standard:
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.
You'd need to define what you mean by valid, but according to the above, it cannot mean "guaranteed behavior as defined by the standard", since it could lead to a "trap representation", i. e. undefined behavior if read.
From C in a Nutshell:
An lvalue is an expression that designates an object, and it
can appear on the left side of an assignment operator.
An lvalue can always be resolved to the corresponding object’s
address, unless the object is a bit-field or a variable declared with the register storage class.
According to the second sentence from the quote, when the object is
a bit-value or a variable declared with the register storage class,
a lvalue can't be resolved to the corresponding object's address.
Why is that?
Given a lvalue which can't be resolved to the corresponding object's
address, how can the lvalue designate an object, and appear on the
left side of an assignment operator?
I think that the following three statements are equivalent:
a lvalue can't be resolved to the corresponding object's address,
a lvalue designate an object,
a lvalue can appear on the left side of an assignment operator.
and either of them can be used as a definition of lvalue. Am I
right?
Thanks.
The minimum addressability resolution is the char. If you want a bit field, that's one or more bits within a char so cannot have its own address, unless you were to allow addresses like 42.6 which would blow the heads off most coders :-)
Variables with register storage class generally can't be addressed because they're not necessarily stored anywhere in memory - that is, after all, what the register storage class means: try to keep this value in a register.
But, even though you cannot get an address for those objects, that doesn't mean you cannot assign to them. For objects held in registers, you just change the register.
And, for bit fields, you can just use the Boolean operations like and/or to manipulate parts of an addressable value.
For example,
int x = 10;
we say that "x designates an int object which stores 10". But what does "designate" exactly mean? Does it mean x behaves like a label which refers to the whole chunk of memory?
x is an identifier.
There is an int object (i.e. a region of storage) containing the value 10.
The identifier x is associated with that int object.
The C standard uses the English word designate to express the relationship between an identifier and the object it identifies. You could say the same thing in several different ways. I said "associate" just now, there are many words we could choose. "x is a label for this region of memory" would be another way.
Note: designating is not limited to identifiers. Other expressions can designate an object too. For example *(&x) also designates the same object, as does *(&x + 0).
When an expression designates an object, the expression may be used to either assign a value to the object, or retrieve the value from the object. (The same syntax covers both of those cases; it depends on context whether the value is read or written).
The word lvalue means an expression that might designate an object (according to the above definition of 'designate').
What is the difference between the following two syntaxes in go?
x := [...]int{ 1:1, 2:2 }
x := []int{ 1:1, 2:2 }
Go's document says "The notation ... specifies an array length equal to the maximum element index plus one". But both the above syntaxes gives same lenght (3).
Is there a name for this operator "..."?
Didn't find a way to search this operator in google.
The first line creates an array using an array literal, its length computed automatically by the compiler. It is detailed in the Composite literals section of the Language Specification.
The notation ... specifies an array length equal to the maximum element index plus one.
Note: this is not to be confused with the ... used to specify variadic parameters or to pass slices as their values. It is detailed in the Function types section of the spec.
The second line uses a slice literal and will result in a slice. Note that under the hood an array will also be created, but that is opaque.