S
Shao Miller
Very well. Agreed.Lets agree to differ then.
Ok. My impression of 'two_d_array[0] + 20' would be thatThis is
very different to what I take the phrase "popular consensus" to mean.
For example, I'd bet that the popular consensus amongst C programmers is
that
int two_d_array[10][10];
two_d_array[0][20] = 42;
is well-defined, but it's hard to find well-reasoned arguments from C
experts to support that view.Aha. My take would make good use of 6.5.2.1,p2:"The definition of the subscript operator [] is that E1[E2] is
identical to (*((E1)+(E2)))."So 'two_d_array[0][20]' becomes (ugh) '(*((*((two_d_array)+(0)))
+(20)))', evaluation of which proceeds as follows:
1. 'two_d_array' slides easily through its parentheses
'(*((*(two_d_array+(0)))+(20)))', 6.5.1,p6.
2. 'two_d_array' is not the operand to 'sizeof' nor '&', so it becomes
an expression having type pointer-to-int[20], pointing to the first
element, per 6.3.2.1,p3. 'sizeof two_d_array[0]' should confirm this..
3. '0' easily slides out of its parentheses.
4. We add '0' to the pointer result in step 2. The declaration
provided an array object with 10 array-of-int objects. The element
with offset 0 is within the bounds (+1) and we have a result with type
pointer-to-int[20]. '(*((*(result))+(20)))' per 6.5.6,p8.
5. The result of step 4 easily slides. '(*((*result)+(20)))'
6. The unary '*' operator yields a result with type int[20].
'(*((result)+(20)))', per 6.5.3.2,p4.
7. The result from step 6 slides. '(*(result+(20)))'
8. So does '20'. '(*(result+20))'
9. The result of step 6 is not an operand to 'sizeof' or '&', has
array type, and is thus an expression having type pointer-to-int,
congruent with step 2's reference.
10. There is an 'int' object within the bounds of the array object at
offset 20, a pointer to this object is the result, congruent with step
4's reference. '(*(result))'
11. The result of step 10 slides. '(*result)'
12. The unary '*' operator yields a result having type 'int' and which
is an lvalue, congruent with the reference from step 6. '(result)'
13. The result of step 12 slides. It's still an lvalue. 'result'
14. The rest is assignment to that lvalue.
Where along here is there sometimes debate, if we can digress for at
least a moment?
I don't think there is much debate. If there is any, I think it is
about what array to use as the bounds.
'two_d_array[0]' should yield a result with type 'int *', with an
intermediary state as an 'int[10]'. So adding 20 should try to move
to the 20th 'int' element in the entire array object. I believe that
6.5.6,p2 excludes an aggregate type, such as an array type.
"For addition, either both operands shall have arithmetic type, or one
operand shall be a pointer to an object type and the other shall have
integer type."
So I don't think an 'int[10]' could be an operand, here. I think the
case for trouble would be:
two_d_array + 20 /* Having an operand with a type going from 'int[10]
[10] to 'int(*)[10]' */
versus:
two_d_array[0] + 20 /* Having an operand with a type going from
'int[10] to 'int *' */
The array-to-pointer conversions come from 6.3.2.1,p3. That's an
example of an implicit conversion.
"...an expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’..."
Well I apologize. I mixed styles here. "pointer-to-int[20]" meaningI got lost in your explanation because you have phrases like "having
type pointer-to-int[20]" and "a result with type int[20]". I'm not sure
what these mean. The last is a C type but it does not occur in the
evaluation so I think you meant something else by it.
"int(*)[20]" and "int[20]" meaning just that. Unfortunately, it's
actually a typo. I should have written '10' instead of '20' in both
places.