K
Keith Thompson
Nicklas Karlsson said:Oh, maybe "does not require an lvalue" was a bad statement, maybe
"does require an rvalue" would be more correct, I do think that the
sizeof operator takes the type of lvalues, and the type of rvalues, it
does not need the lvalue to evaluate to an rvalue, the lvalue doesn't
even need to designate valid object, it only needs to know the type
imposed by the lvalue.
Some context from the previous article would have made this clearer.
The phrase "does require an rvalue" doesn't make much sense.
The C standard uses the term "rvalue" to mean "the value of an
expression"; it mentions this in passing in a single footnote.
I find that any statement about C that uses the word "rvalue"
can be expressed more clearly without using the word "rvalue".
The sizeof operator, when its operand is an expression, determines the
type of the expression and yield the size, in bytes, of that type
(equivalently, the size of an object of that type). It doesn't matter
at all whether that expression is an lvalue or not. In most cases, the
expression isn't evaluated; it's merely analyzed (at compile time) to
determine its type. (The exception is when it's a variable-length
array.)
I guess my beef is with the term "evaluation", I do not quite
understand it. To me, it seems as an lvalue in a context that requires
an lvalue will partly evaluate at compile time (if its a normal memory
based variable for example), that is, being compiled into code that
identifies an object, but its not fully evaluated, at runtime the
offset decided for this variable will be used to calculate the
address.
What is this "offset" you're talking about? Offset of what, relative to
what?
When an lvalue (which, again, is a kind of expression) is evaluated
in a context that requires an lvalue, the result of the evaluation
is, in effect, the identity of the object that it designates.
For example, given:
x = 42;
``x'' is an lvalue that appears in a context that requires an lvalue.
Evaluating ``x'' in a non-lvalue context would yield the value
stored in the object named "x". Evaluating ``x'' in *this* context
identifies the object without reading its value; the identity of
the object is used to determine where the assignment operator will
store the value 42.
Whether this evaluation takes place at compile time or at run time
is not specified, and is not particularly important. If x is an
external variable, the resolution might take place at link time.
If the lvalue, rather than ``x'', is ``arr[rand()%MAX]'', then at
least some of the evaluation must take place at run time. In that
sense, it's not fundamentally different from non-lvalue evaluation.
But then we have register variables, I do not see any
possibility for it not to be fully evaluated at compile time, it knows
the register the lvalue uses, and it knows the type (therefore object
size, that is, part of the register used) of the lvalue. Here is where
I start going "is this really evaluation?" because I don't see that
any action is needed (no evaluation needed, if this isn't what you
call evaluation).
My advice: Don't worry about it. Expressions, whether they're
lvalues or not, are evaluated (or not), yielding either a value
or the identity of some object. Clever compilers can sometimes
pre-calculate some or all of the result, for example by replacing
``2 + 2'' with ``4''. In some contexts expressions are required to
be evaluated at compile time, for example case label expressions.
But that's mostly an implementation detail.
I'd be grateful is someone could tell me more about what evaluation
really means. MSDN says its:
* Computes a value
* Designates an object or function
* Generates side effects
That's about right.
...but does not say the nature of it, if the code generated could be
considered evaluation for example.
The *nature* of evaluation is that it computes a value, designates
an object or function, and/or generates side effects. Any code
generated is just an implementation-specific mechanism.
Are you assuming that a C expression, or an entire C program,
is a way to specify machine code? That's one way to think of
it, but not the best. A better way to think of it is that a C
expression or program is a way to specify certain *behavior*,
such as producing some output. The machine code is nothing more
or less than a mechanism used to achieve that goal.