Re: Evaluating unary *
- From: James Kuyper <jameskuyper@xxxxxxxxxxx>
- Date: Thu, 14 Feb 2008 12:25:19 GMT
cr88192 wrote:
"James Kuyper" <jameskuyper@xxxxxxxxxxx> wrote in message news:D5Bsj.149$xh.97@xxxxxxxxxxxcr88192 wrote:
...
int arr[12];
'arr' exists, and is a 1D array.
'&arr' creates a 2D array ('int _[1][12]').
&arr doesn't create anything. It has a value which points at arr. That value can be used with the same syntax as would be used to access a 2D array of the kind you're referring to, but that 2D array is just a different way of looking as the same object that was already created by the definition of 'arr'.
by this reasoning, depending on where "arr" is, it is not "created" at all...
No, it is created by the line where arr is defined.
but, from the POV of the implementation, we have a "new" array that just so happens to overlap the same space as the old array (and isn't as such bound to a variable).
It's not a new array in the old location, but the same old array seen from a different point of view. Any need to set aside memory to keep
track of the details of this new point of view is implementation specific, and has nothing to do with C itself. For most conventional implementations, the expression &arr requires no special handling beyond insertion of the appropriate address into a suitable register. The fact that some implementation chooses to do something more complicated is not relevant as far as the C standard is concerned.
arr[0] is an lvalue, but 'arr' itself is not an lvalue.
to me, it makes sense to return a pointer to the first value of an array, but to return the address of the pointer to the first value of an array (what is implied, but is an incorrect interpretation in this case), is not directly possible as such.
I agree that it's incorrect; I can't figure out why you consider that it's implied. What you describe would be represented by the illegal code &&arr[0], not &arr.
(except that '&&arr[0]' wouldn't parse as such...).
It should parse; it's a constraint violation, not a syntax error. As I
said less precisely: "illegal code" - a diagnostic is required. The behavior is undefined, precisely because the behavior that would otherwise have been defined for this construct becomes meaningless for precisely the reasons you incorrectly ascribe to &arr.
....
I am not denying what is valid according to the standard (the '&arr' construction makes sense in the context of the standard, and also in the abstract typesystem), what I am arguing is that it is counter-intuitive and problematic implementation-wise (aka: an ugly hack...).
my original response was me being unaware that implementations were able to pull it off (or that people actually wrote such things and expected them to work...).
This is a very elementary part of C; I've used it routinely on many
occasions. I'd be very surprised at a compiler which failed to correctly implement it.
....
The expression &arr doesn't involve the creation of any pointer value which points at the first element of arr. It does create a pointer value which points at arr itself, and treats the entirety of arr as the first element in an array containing exactly one element of type int[12]. However, that's not a change in type to an existing pointer, that's the creation of a brand-new pointer.
no.
in terms of implementation, it is exactly the reverse of this:
we can regard int[12] and int[1][12] as different types;
however, if arr is at, for example, 0x403C0000, &arr will tend to have exactly the same address.
The value of the expression &arr is a pointer value; that value doesn't have an address at which it is stored, at least as far as standard C is concerned. It is not an lvalue, and it is therefore a constraint violation to even attempt to determine it's address. Depending on the
implementation, the closest thing it will have to an 'address' is a
register number.
eg:
assert(((void *)arr)==((void *)(&arr)));
That works because in the first context arr is an expression of array type which is converted into a pointer to its first element. In the second context, since it is the direct operand of the '&' operator, no such conversion occurs, and the result is a pointer to the array itself. Those two pointers, suitably converted, should indeed compare equal because they point at the same location in memory, though I can't find a citation from the standard which explicitly says so. There an explicit statement of such a requirement for a structure and it's first member, there should be similar wording for an array and it's first element, but I'm having trouble finding it.
Larry Jones made reference to this problem; it may have been overlooked - it's certainly the committee's intent that this be true, and a lot of code has been written on the assumption that it is true.
Saying that arr, when converted to a pointer to its first element, points at the same location as is pointed at by &arr, is very different from saying that the array arr has the same address as pointer value &arr, because the address of &arr is a meaningless concept.
so, the question then is whether one regards a pointer as "simply an address", or as "a type and an address" (in the latter, your comment is valid, in the former, it is not).
As far as the C standard is concerned, a pointer value most definitely
has a type, in addition to identifying a memory location.
... to make it seem as if the operation has worked (note, by this I view things, as generally do most archs, that a
It did not only "seem as if [it] has worked", it did work. I don't understand why you believe otherwise.
it works only because the compilers hack over this case, not because this operation is actually meaningful.
It seems meaningful to me. What you call a hack is what I call a correct
implementation of the required semantics; that's not necessarily a
contradiction - correct code is sometimes also a hack. However, you seem to be saying that any code which correctly implements the required semantics is a hack, and I don't agree with that judgment.
....
after all, when we cast a pointer, is the pointer changed? in most archs, no...
True; but as far as the C standard is concerned, it can be changed.
It is not uncommon for platforms to have a smallest addressable unit of storage which is longer than 8 bits, and C implementations for such platforms often choose a value for CHAR_BIT which is a fraction of the word size. Such implementations often have pointers of different sizes and representations depending upon whether or not the pointed-at type has a size that is a multiple of the word size.
Code which assumes that all pointer types have the same size, alignment requirements, and representation is, at best, unportable.
so, in terms of what happens:
int arr[12];
int t;
'&arr', and '&t' reflect different operations (at the C level they are very similar, but at the ASM level they are not).
Both operations create pointers which point at the corresponding named object. Conceptually, each pointer consists of something (usually an address) which identifies a location in memory for the object, plus some rules that impose different limitations on what operations can be performed on the pointer in the two cases. The location in memory is the only thing that matters at the machine code level when those expressions are evaluated. The different rules that apply to the two pointers determine how the values of those expressions may be used, and very different instructions may be generated from code that syntacticly does the same thing with each pointer.
it seems there was a break.
&arr, and &t, would generate essentially the same code (a 'lea' on x86 or similar), however, so would arr.
Yes, all three of those expressions, if evaluated, produce pointers to the beginning of named objects, so a key step in the evaluation of any of those expressions is to load the address of that named object into a register. The differences between &arr and arr lie entirely in type of the pointer they create. The type, in turn, determines which further operations are permitted on that pointer, and also what the semantic meaning of those operations is. For instance, *&arr means something quite different from *arr.
.
- Follow-Ups:
- Re: Evaluating unary *
- From: cr88192
- Re: Evaluating unary *
- From: Keith Thompson
- Re: Evaluating unary *
- References:
- Evaluating unary *
- From: Peter Nilsson
- Re: Evaluating unary *
- From: cr88192
- Re: Evaluating unary *
- From: lawrence . jones
- Re: Evaluating unary *
- From: Jeff Schwab
- Re: Evaluating unary *
- From: cr88192
- Re: Evaluating unary *
- From: lawrence . jones
- Re: Evaluating unary *
- From: cr88192
- Re: Evaluating unary *
- From: James Kuyper
- Re: Evaluating unary *
- From: cr88192
- Evaluating unary *
- Prev by Date: Re: Evaluating unary *
- Next by Date: Re: Evaluating unary *
- Previous by thread: Re: Evaluating unary *
- Next by thread: Re: Evaluating unary *
- Index(es):
Relevant Pages
|