Address of array behavior in pointer arithmetic

J

joshc

So I've read the relevant sections in the FAQ and the other threads on
this topic but didn't find the exact answer to my question. A fellow
developer wrote the following in some code:

uint16 arr[10];

uint16 val;

val = *(&arr + 0);

So I know that &arr is a pointer to an array of 10 ints versus arr
which is a pointer to int when used in value context. In my case my
compiler ended up storing the address of 'arr' in 'val' for the code
above. Can someone explain what really happens in the code snippet
above? In other words what the (&arr + 0) expression evaluates to in
terms of type, etc.

Thanks.
 
J

jackdorse

uint16 arr[10];
uint16 val;

val = *(&arr + 0);

So I know that &arr is a pointer to an array of 10 ints versus arr
which is a pointer to int when used in value context. In my case my
compiler ended up storing the address of 'arr' in 'val' for the code
above. Can someone explain what really happens in the code snippet
above? In other words what the (&arr + 0) expression evaluates to in
terms of type, etc.

Thanks.

arr is a simple pointer of the array. when u say &arr it is something
similar to pointer to pointer.

so when u try to dereference (&arr + 0) it results into an address.
Also, if u look at the warning generated by gcc compiler

"warning: assignment makes integer from pointer without a cast"

makes the point very clear.
 
D

deepak

As said,
val = arr. But if gives array name, it 'll generate the starting
address of array.

This one 'll be correct.

main()
{

int val;
int arr[10];

val = **(&arr + 0);

}

Thanks,
Deepak.
jackdorse said:
uint16 arr[10];

uint16 val;

val = *(&arr + 0);

So I know that &arr is a pointer to an array of 10 ints versus arr
which is a pointer to int when used in value context. In my case my
compiler ended up storing the address of 'arr' in 'val' for the code
above. Can someone explain what really happens in the code snippet
above? In other words what the (&arr + 0) expression evaluates to in
terms of type, etc.

Thanks.

arr is a simple pointer of the array. when u say &arr it is something
similar to pointer to pointer.

so when u try to dereference (&arr + 0) it results into an address.
Also, if u look at the warning generated by gcc compiler

"warning: assignment makes integer from pointer without a cast"

makes the point very clear.
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

deepak said:
As said,
val = arr. But if gives array name, it 'll generate the starting
address of array.

This one 'll be correct.
Not really.
&arr isn't an int** , it is an int (*)[10].
main()
{

int val;
int arr[10];

val = **(&arr + 0);

}

Thanks,
Deepak.
jackdorse wrote:
 
C

Chris Dollin

joshc said:
So I've read the relevant sections in the FAQ and the other threads on
this topic but didn't find the exact answer to my question. A fellow
developer wrote the following in some code:

uint16 arr[10];

uint16 val;

val = *(&arr + 0);

Never mind the technical answer to your question: what on /Earth/
was your fellow developer /thinking/ when they wrote that?
 
K

Keith Thompson

jackdorse said:
uint16 arr[10];

uint16 val;

val = *(&arr + 0);

So I know that &arr is a pointer to an array of 10 ints versus arr
which is a pointer to int when used in value context. In my case my
compiler ended up storing the address of 'arr' in 'val' for the code
above. Can someone explain what really happens in the code snippet
above? In other words what the (&arr + 0) expression evaluates to in
terms of type, etc.

Thanks.

arr is a simple pointer of the array. when u say &arr it is something
similar to pointer to pointer.

That's wrong. &arr is the address of the array; there's no
pointer-to-pointer anywhere.

Please read section 6 of the comp.lang.c FAQ <http://www.c-faq.com/>.

(And please don't use silly abbreviations like "u".)
 
J

jackdorse

Nils said:
deepak said:
As said,
val = arr. But if gives array name, it 'll generate the starting
address of array.

This one 'll be correct.
Not really.
&arr isn't an int** , it is an int (*)[10].

agreed. srry for the mistake
 
J

jackdorse

Nils said:
deepak said:
As said,
val = arr. But if gives array name, it 'll generate the starting
address of array.

This one 'll be correct.
Not really.
&arr isn't an int** , it is an int (*)[10].

agreed. thanx for drawing my attention
 
D

deepak

Nils,

Just want to know mistake was from me or Jachorse?


Chris said:
joshc said:
So I've read the relevant sections in the FAQ and the other threads on
this topic but didn't find the exact answer to my question. A fellow
developer wrote the following in some code:

uint16 arr[10];

uint16 val;

val = *(&arr + 0);

Never mind the technical answer to your question: what on /Earth/
was your fellow developer /thinking/ when they wrote that?
 
J

joshc

Keith Thompson wrote:

That's wrong. &arr is the address of the array; there's no
pointer-to-pointer anywhere.

Please read section 6 of the comp.lang.c FAQ <http://www.c-faq.com/>.

(And please don't use silly abbreviations like "u".)

If you read my post I said I read the FAQ but was asking for how that
expression ended up with the address of the array. The concept of
pointer to array of 10 ints seems very abstract to me. In actual terms
it would seem to point to the same address as 'arr' itself but has a
different type. Why that different type causes the result I mention is
what I want to know.

Regarding abbreviations like "u", are you referring to my use of
"uint16". If that's the case then those are types we've defined and it
isn't an abbreviation. It's definition is based on which implementation
we're using and that's why I didn't include the typedef.

Thanks.
 
J

joshc

Chris said:
joshc said:
So I've read the relevant sections in the FAQ and the other threads on
this topic but didn't find the exact answer to my question. A fellow
developer wrote the following in some code:

uint16 arr[10];

uint16 val;

val = *(&arr + 0);

Never mind the technical answer to your question: what on /Earth/
was your fellow developer /thinking/ when they wrote that?

I guess he meant to say *(&arr[0] + 0) but for some reason or the other
thought &arr might result in the same. I'm sure a lot of people don't
know that that is incorrect. I myself have been programming in C for
quite some time and consider myself fairly proficient and althought
I've never used &arr I wasn't sure that it was wrong. I reviewed his
code and pointed out that that was probably the error and sure enough
it was. As far as adding 0 in the real code it is replaced by a
function parameter.
 
P

pete

Nils O. Selåsdal said:
As said,
val = arr. But if gives array name, it 'll generate the starting
address of array.

This one 'll be correct.
Not really.
&arr isn't an int** , it is an int (*)[10].

That doesn't matter.
The result of dereferencing (&arr) is an expression of array type,
which converts to an expression of pointer type.

There's nothing wrong with the code quoted below:
int val;
int arr[10];

val = **(&arr + 0);
 
C

Chris Torek

[someone] wrote the following in some code:

uint16 arr[10];
uint16 val;

val = *(&arr + 0);

So I know that &arr is a pointer to an array of 10 ints versus arr
which is a pointer to int when used in value context.
Correct.

Can someone explain what really happens in the code snippet
above? In other words what the (&arr + 0) expression evaluates to in
terms of type, etc.

&arr produces a value of type "pointer to (array 10 of uint16)"
(presumably uint16 is a typedef-name for some actual C type, perhaps
"unsigned short"), pointing to the entire array "arr". Adding zero
to this value leaves the value unchanged, so you still have a
pointer that points to the entire array. See also:

http://web.torek.net/torek/c/pa.html

for a graphical depiction of what a "pointer to an entire array"
means. Had you added 1 instead of 0, the "big circle" would move
forward by "one whole array", as shown on the page above.

In any case, after stepping forward by "zero whole arrays" -- so
that the pointer still points to the entire array -- this pointer
is fed to the unary "*" operator. The "*" operator follows the
pointer to the thing to which it points, namely, the entire array.
Since "the thing to which it points" is an array *object*, but this
is the right hand side of an "=" assignment, we need a value.
This array object thus runs into The Rule about arrays and pointers
in C. The expression's value is then the value found by computing
a pointer to the first element of the array, i.e., &arr[0].

Of course, this value is a pointer, not a "uint16", so the C compiler
gives you a complaint of some sort, and then probably generates
code that first wrecks the full (typically 32 or 64 bit) address,
and places some 16-bit wreckage into the "uint16" variable named
"val".
 
K

Keith Thompson

joshc said:
Keith Thompson wrote:

(And don't quote signatures unless you're commenting on them. Thanks.)
If you read my post I said I read the FAQ but was asking for how that
expression ended up with the address of the array. The concept of
pointer to array of 10 ints seems very abstract to me. In actual terms
it would seem to point to the same address as 'arr' itself but has a
different type. Why that different type causes the result I mention is
what I want to know.

The important thing to remember is that arrays are not pointers, and
pointers are not arrays. A pointer to an array of 10 ints is really
no more abstract than a pointer to any other type.

When you declare

uint16 arr[10];

you're declaring an array object. No pointer object is created
anywhere. The expression &arr is a pointer *value*; it points to the
array object. It's exactly the same as:

int x;

where &x evaluates to a pointer value, which points to the int object.

Pointers point to objects. If &arr were, as you suggest, a pointer to
pointer, there would have to be some pointer object for it to point
to. There isn't.

In most contexts, an expression of array type is implicitly converted
to a pointer to its first element. The exceptions to this rule are
the operand of a unary sizeof or "&" operator, or a string literal
used in an initializer for an array object.

[..]
Regarding abbreviations like "u", are you referring to my use of
"uint16".

No, I'm referring to the use of "u" for "you" (which I see you're not
using anymore; thank you).
 
J

Joe Wright

joshc said:
So I've read the relevant sections in the FAQ and the other threads on
this topic but didn't find the exact answer to my question. A fellow
developer wrote the following in some code:

uint16 arr[10];

uint16 val;

val = *(&arr + 0);

So I know that &arr is a pointer to an array of 10 ints versus arr
which is a pointer to int when used in value context. In my case my
compiler ended up storing the address of 'arr' in 'val' for the code
above. Can someone explain what really happens in the code snippet
above? In other words what the (&arr + 0) expression evaluates to in
terms of type, etc.

Thanks.
The dereference operator (*) and the address of operator (&) are
complementary and cancel each other out. *(&arr) == arr.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top