Re: Evaluating unary *




"James Kuyper" <jameskuyper@xxxxxxxxxxx> wrote in message news:D5Bsj.149$xh.97@xxxxxxxxxxx
cr88192 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...

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).

for example, in my compiler, at present, anything beyond a 1D array (with a certain size limit, like 4096 or something) ends up having a context created for it (for small 1D arrays have everything stored in the 'type value', in the same bits that would otherwise refer to the context). likewise, we can index an array, getting an array of one-less order, or a value, but, to increase the order, requires creating a new context.

as such, a new array is "created" under these terms.


....
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...).
under my views, &arr, and &(&arr[0]), represent essentially the same construction (only, that the latter is not actually required to work, but otherwise both would imply similar implementation issues, apart from introducing a finer distinction that exists within my implementation of multidimensional arrays...).


It is true that in most contexts that "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" (6.3.2.1p3). However, it seems almost as if you're unaware of the fact that there are three exceptions to this rule: when such an expression "is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array".

The expression arr == &arr[0] demonstrates this rule. Because &arr[0] is parsed the same as &(arr[0]), none of the exceptions apply to either occurrence of 'arr' in that expression, and both decay into pointers to the first element of arr.

However, when &arr is not followed by an postfix operator, then the second exception does apply, and arr does not decay into a pointer to the first element of arr.


that is true, but does not seem particularly relevant.

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...).


instead, the compiler does something different:
the pointer is still, technically, to the first item in the array;
it then just changes the type, ...

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.

eg:
assert(((void *)arr)==((void *)(&arr)));

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).


... 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.


pointer is itself an untyped address, so 2 pointers are the same pointer even if their types are different, and the idea of pointers having type is primarily a compiler/language-imposed idiom).

A pointer is a C concept; addresses whose type means nothing to the hardware are commonly used in the implementation of C pointers, but such addresses are not themselves pointers. They become pointers only when interpreted as such by code generated by the C compiler. The type of the pointer is a key aspect of that pointer, but it is used to determine which code is generated by the C compiler for any given use of the pointer; it is not a feature of the address used to implement that pointer.


however, as noted, this type none the less, only exists in the compiler.
that different sequences of machine instructions are used for different types is, in this context, irrelevant. the instructions used make a difference, but, usually, which instructions are used with what pointers (apart from possibly alignment issues and similar) makes almost no difference to the arch.


after all, when we cast a pointer, is the pointer changed? in most archs, no...
after all, 'void *' is a valid type for returning any kind of allocated object (if it were not, we could not have such things as malloc...).

none the less, we cast or assign a pointer, and its type (according to the compiler) is changed.

(or, as an analogy: "what is the value of human life according to the laws of physics?", it is N/A...).


...
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.

lea eax, [arr] ;&arr
lea ecx, [t] ;&t
lea edx, [arr] ;arr

*(&arr+1)
lea eax, [arr]
add eax, 48

arr+1
lea eax, [arr]
add eax, 4

&t+1
lea eax, [t]
add eax, 4

*(&t+1) //ignoring obvious transformations
lea eax, [t]
add eax, 4
mov eax, [eax]

int **appA[10];

*((*(apA+5))+1)

lea eax, [apA]
add eax, 20
mov eax, [eax]
add eax, 4
mov eax, [eax]

....


...
sorry, I am not very clear...

With that, I can agree.

.



Relevant Pages

  • Re: Evaluating unary *
    ... 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'. ... the expression &arr requires no special handling beyond insertion of the appropriate address into a suitable register. ... 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, is not directly possible as such. ... 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. ...
    (comp.std.c)
  • Re: Binary file from C++ to Matlab
    ... By convoluting array and pointer syntax, ... arr is an array of doubles but also an acronym for &arr. ... ptr is a pointer to a constant array literal. ...
    (comp.soft-sys.matlab)
  • Re: multi dimensional arrays as one dimension array
    ... Are you of the opinion that one or both of memcpy(p, arr, sizeof arr) ... way of converting a two-dimensional array into a one-dimensional ... &arr) is supposed to be pointer constrained legally to range over ... arrays of character type and other objects treated as arrays ...
    (comp.lang.c)
  • Re: Binary file from C++ to Matlab
    ... By convoluting array and pointer syntax, ... arr is an array of doubles but also an acronym for &arr. ... ptr is a pointer to a constant array literal. ...
    (comp.soft-sys.matlab)
  • Re: char **argv & char *argv[]
    ... "pointer to pointer to char". ... >> pointer)) pointing to the first element of an array. ... so we have to start adding more context. ... type "pointer to char", rather than "array MISSING_SIZE of char". ...
    (comp.lang.c)

Loading