Pointer-to-array - screwed up my mind ...

I

Irrwahn Grausewitz

Hey, y'all.

While doing some pointer experiments I encountered
a problem. I know that I know the answer already,
but trying to remember I just screwed up my mind.
I wonder if someone would be so kind to enlighten
me, please.

Consider the code below; my specific questions
are embedded in the comment lines:

/* sample code for pointer-to-array problem */
#include <stdio.h>
#include <stdlib.h>

int main( void )
{
int i;

int arr[5][10];
/*
** Declare 'arr' as 'array of 5 arrays of 10 ints',
** right?
*/

int (*ap)[10];
/*
** Declare 'ap' as 'pointer to array of 10 ints',
** right?
*/

ap = (int (*)[10])arr[0]; /* this works; accepted. */
ap = &arr[0]; /* this works, too; why? */

/*
** But if I try this:
** ap = arr[0];
** my compiler produces a diagnostic:
** "Warning: assignment from incompatible pointer type"
**
** arr[0] should already serve as a
** pointer to array of 10 ints, shouldn't it ???
*/

for ( i = 0; i < 5; i++ )
printf( "ap+%d %s &arr[%d]\n",
i,
(( ap+i == &arr ) ? "==" : "!=" ) ,
/* ^^^^^^^ WHY NOT: arr ??? */
i );

return EXIT_SUCCESS;
}
/* end sample code */

If this is a faq, I apologize for not being able to
find it in the faq list ... :)

Thanks,

Irrwahn
 
S

Simon Biber

Irrwahn Grausewitz said:
/* sample code for pointer-to-array problem */
#include <stdio.h>
#include <stdlib.h>

int main( void )
{
int i;

int arr[5][10];
/*
** Declare 'arr' as 'array of 5 arrays of 10 ints',
** right?
*/
Yes.

int (*ap)[10];
/*
** Declare 'ap' as 'pointer to array of 10 ints',
** right?
*/
Yes.

ap = (int (*)[10])arr[0]; /* this works; accepted. */

If you need a cast, you're probably doing something unsafe.
In this case, you're converting from arr[0] which has type
'array of 10 int' or as a value 'pointer to int', to type
'pointer to array 10 of int'. While these two pointers do
point to the same location in memory, they are have quite
different semantics. Note how
arr[0] + 1 points to arr[0][1]
whereas
ap + 1 points to arr[1]
ap = &arr[0]; /* this works, too; why? */

This is the correct way, as both sides of the assignment have
the same type. You can also do:
ap = arr;
Because there is is an implicit conversion from any array type
into a pointer to its first element. So, although arr has type
'array 5 of array 10 of int' it is automatically converted to
'pointer to array 10 of int'.
/*
** But if I try this:
** ap = arr[0];
** my compiler produces a diagnostic:
** "Warning: assignment from incompatible pointer type"

Exactly. As explained above, arr[0] is an array of 10 int. When
used in a value context, it is converted into a pointer to its
first element, so becomes a pointer to arr[0][0], a pointer to
int. This is the wrong type.
** arr[0] should already serve as a
** pointer to array of 10 ints, shouldn't it ???

No. If you want a pointer to array of 10 ints, simply write arr
by itself, or to be explicit, write &arr[0].

arr is an array of 5 arrays, each of 10 ints. It is not a pointer.
When used in an expression, other than as the argument of a sizeof
or address-of (&) operator, it is converted into a pointer to its
first element. Not into a pointer to itself!

arr[0] is the first array of 10 ints. It is not a pointer. When
used in an expression, other than as the argument of a sizeof or
address-of (&) operator, it is converted into a pointer to its
first element. Not into a pointer to itself!
 
I

Irrwahn Grausewitz

ap = arr; /* would also work. */

This is because of Chris Torek's THE RULE: When used in a value
context (rather than in an assignment or initialisation context), an
array decays into a pointer to its first element.

Ah, yes, that was the missing link I couldn't remember!!!
(BTW: I wish there was a collection of CT's posts available :))))
** But if I try this:
** ap = arr[0];
** my compiler produces a diagnostic:
** "Warning: assignment from incompatible pointer type"

This is because ap is a pointer to an array of 10 ints, but arr[0]
is an array of 10 ints. It would be the same as trying to assign an
int to a pointer to an int.
Yes, of course, now I notice; sigh ...
** arr[0] should already serve as a
** pointer to array of 10 ints, shouldn't it ???

No. In a value context, it would "serve as" a pointer to _an int_,
not to _an array of 10 ints_.
.... dito ...
(( ap+i == &arr ) ? "==" : "!=" ) ,
/* ^^^^^^^ WHY NOT: arr ??? */


Because they differ in indirection levels. ap+i == arr+i would also
work.

.... dito ...

I hope I'll never forget about these issues again!

Thanks Joona!

Irrwahn
 
L

LibraryUser

Irrwahn said:
.... snip ...

Ah, yes, that was the missing link I couldn't remember!!!
(BTW: I wish there was a collection of CT's posts available :))))

There is. Search google groups for articles on c.l.c with author
Chris Torek.
 
I

Irrwahn Grausewitz

LibraryUser said:
There is. Search google groups for articles on c.l.c with author
Chris Torek.

Yes, of course. I tried to make a running gag last longer ...
not a good joke, possibly. :-|
 
D

Deepak

The declaration
int A[5][10] ;
means to compiler is an array of 10 int
placed sequentially in 5 rows.
So A is actually a collection 5 single dimensional array of 10 ints.
And as the language says the the array name is a pointer to its first
element
the the type of the A is really int (*)[10] which is pointer to sigle
dimensional array of 10 ints.
The implication of the above statement is if u do:
int (*p)[10];
p = A;

Then the p+1 will point to the next row.
This is what the pointer arithmatic.
The compiler interanally adjust the the offset from base address as
follow knowing that the type of A is pointer to array 10 of ints.
offset= 10*sizeof(int)
p+1= base address(A) + offset

I hope it answers to your query.
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top