Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Question about pointers and multi-dimension arrays

Reply
Thread Tools

Question about pointers and multi-dimension arrays

 
 
DiAvOl
Guest
Posts: n/a
 
      12-27-2007
Hello everyone, merry christmas!

I have some questions about the following program:

arrtest.c
------------

#include <stdio.h>

int main(int agc, char *argv[]) {
int array2d[2][2] = { {1,2} , {3,4} };
int (* arrp)[2] = array2d;

printf("&array2d = %p\tarray2d = %p\t*array2d = %p\n", &array2d,
array2d, *array2d);
printf("&arrp = %p\tarp = %p\t*arrp = %p\t**arp = %d\n", &arrp,
arrp, *arrp, **arrp);

return 0;
}

When I compile and run the program I get the following results:

&array2d = 0xbfd9e880 array2d = 0xbfd9e880 *array2d = 0xbfd9e880
&arrp = 0xbfd9e890 arrp = 0xbfd9e880 *arrp =
0xbfd9e880 **arrp = 1

My questions are:

Why is the address of array2d (&array2d), the value (array2d) and the
contents of that value (*array2d) all the same ? (0xbfd9e880)

array2d contains the value: 0xbfd9e880. When dereferenced (*array2d)
it gives the same value, 0xbfd9e880
But when the same address is dereferenced again (**array2d) it gives
an integer (1) and not an address like above.

How does the compiler "understands" if it should return a pointer or
the value stored in that address?

How does the compiler stores array variables so that &array == array ?

Thanks for your time, I hope you will understand my questions
 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      12-27-2007
DiAvOl said:

<snip>

> int array2d[2][2] = { {1,2} , {3,4} };


<snip>

> Why is the address of array2d (&array2d), the value (array2d) and the
> contents of that value (*array2d) all the same ?


They aren't the same, because they have different types. &array2d has type
int (*)[2][2], array2d has type int[2][2] (which is converted into a value
of type int(*)[2] when used in value contexts), and *array2d has type
int[2] (which is converted into a value of type int * when used in value
contexts).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
 
 
 
Malcolm McLean
Guest
Posts: n/a
 
      12-27-2007

"DiAvOl" <(E-Mail Removed)> wrote in message news:06ce14cb-

> int main(int agc, char *argv[]) {
> int array2d[2][2] = { {1,2} , {3,4} };
> int (* arrp)[2] = array2d;
>
> printf("&array2d = %p\tarray2d = %p\t*array2d = %p\n", &array2d,
> array2d, *array2d);
> printf("&arrp = %p\tarp = %p\t*arrp = %p\t**arp = %d\n", &arrp,
> arrp, *arrp, **arrp);
>
> return 0;
> }
>

The important thing to know about multidimensional arrays in C 89 is that
they are effectively broken. Whilst they can be declared and used, the
syntax needed to do anything much with them, like pass them to other
functions, is too complicated. They also cannot be resized at runtime.

So just forget about them until you are familiar with most of the rest of
the language. Any multi-dimensional array can easily be emulated with a
single dimension.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

 
Reply With Quote
 
DiAvOl
Guest
Posts: n/a
 
      12-27-2007
0xbfd9e880 <=== Memory address
------------
| 1 | <=== Contents
------------

My point is, how can the address 0xbfd9e880 hold both an address and a
number ?

When array2d is dereferenced (*array2d) it should return the contents
of it's value (contents of memory location 0xbfd9e880) but it returns
the same address.

When array2d is double dereferenced (**array2d) it's the same as
*(*array2d), *array2d as we saw before is the address 0xbfd9e880 so
when it is dereferenced this time, it returns an integer.

How can the compiler determine when to return an integer and when to
return the address?

Thanks for your fast reply
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      12-27-2007
Malcolm McLean said:

<snip>

> The important thing to know about multidimensional arrays in C 89 is that
> they are effectively broken.


I disagree. They work just fine if you treat them right.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      12-27-2007
DiAvOl said:

> 0xbfd9e880 <=== Memory address
> ------------
> | 1 | <=== Contents
> ------------
>
> My point is, how can the address 0xbfd9e880 hold both an address and a
> number ?


Please switch, if necessary, to a non-proportional font such as Courier. It
will make the following diagram clearer.

| M |
| a +-----+-----+-----+-----+---
| i | 1 | 3 | 5 | 7 |
| n X-----+-----+-----+-----+--
| High Street
| R +-----+-----+-----+-----+---
| o | 2 | 4 | 6 | 8 |
| a +-----+-----+-----+-----+-
| d |

See the X? It represents a single point on the Earth's surface. We can
think of this point as "1 High Street" if we like - so in that sense it
can be thought of as an address. On the other hand, it's also the corner
of a living room. On the other other hand, it's also a brick. On the other
other other hand, it's also a Carbon atom. The question "what will we find
at X?" depends on the level at which we're asking the question.


> When array2d is dereferenced (*array2d) it should return the contents
> of it's value (contents of memory location 0xbfd9e880) but it returns
> the same address.


Crank up the magnification on your binoculars, and what you see at X will
change - but it's still at the same place, isn't it?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
Reply With Quote
 
DiAvOl
Guest
Posts: n/a
 
      12-27-2007
I perfectly understand what you are saying. I'll try to describe my
question better.

Suppose I am the C compiler and I see the following constructs:

1) printf("%d", *p); // p is an int pointer

I should fetch the address which p contains and find an int value
there.

All fine with this one

2)
Having:

int array2d[2][2] = { {1,2} , {3,4} };

&array2d = 0xbfd9e880 array2d = 0xbfd9e880 *array2d = 0xbfd9e880

I (the compiler) see the construct: printf("%p", *array2d); .

I should fetch the address which array2d contains (0xbfd9e880) and
find an int pointer there. This returns 0xbfd9e880, so the address
0xbfd9e880 contains the int pointer 0xbfd9e880.

Then I see the construct: printf("%d", **array2d);

I should fetch the address which *array2d contains (0xbfd9e880 as we
saw above) and find an int value there

But I saw before that 0xbfd9e880 contains the int pointer 0xbfd9e880
not an int number... I am confused





Thanks very much for your time and example and sorry for my bad
english.







 
Reply With Quote
 
Ravishankar S
Guest
Posts: n/a
 
      12-27-2007

"DiAvOl" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hello everyone, merry christmas!
>
> I have some questions about the following program:
>
> arrtest.c
> ------------
>
> #include <stdio.h>
>
> int main(int agc, char *argv[]) {
> int array2d[2][2] = { {1,2} , {3,4} };
> int (* arrp)[2] = array2d;
>
> printf("&array2d = %p\tarray2d = %p\t*array2d = %p\n", &array2d,
> array2d, *array2d);
> printf("&arrp = %p\tarp = %p\t*arrp = %p\t**arp = %d\n", &arrp,
> arrp, *arrp, **arrp);
>
> return 0;
> }
>
> When I compile and run the program I get the following results:
>
> &array2d = 0xbfd9e880 array2d = 0xbfd9e880 *array2d = 0xbfd9e880
> &arrp = 0xbfd9e890 arrp = 0xbfd9e880 *arrp =
> 0xbfd9e880 **arrp = 1
>
> My questions are:
>
> Why is the address of array2d (&array2d), the value (array2d) and the
> contents of that value (*array2d) all the same ? (0xbfd9e880)


Here is what I can think of (subject to correction of the experts..)

the typeof(array2d) = "pointer to an array of 2 ints". But array2d is an
r-value , not an l-value. This may be the reason why
&array2d evaluates to the same address even though the typeof(&array2d) ==
"pointer to a pointer to array of 2 ints".
Finally *array2d has the type "array of 2 ints". But in C array is not first
class type and *array2d is not a "lvalue". Thus *array2d evaluates
to the same as array2d.
A case where the expressions have different types , but same values..!

>
> array2d contains the value: 0xbfd9e880. When dereferenced (*array2d)

array2d does not "contain" the value 0xbfd9e880 but rather evaluates to that
value but having the type "pointer to an array of 2 ints".



> it gives the same value, 0xbfd9e880
> But when the same address is dereferenced again (**array2d) it gives
> an integer (1) and not an address like above.

I am not sure how the compiler understands **array2d. Perhaps someone could
help here..

>
> How does the compiler "understands" if it should return a pointer or
> the value stored in that address?
>
> How does the compiler stores array variables so that &array == array ?
>
> Thanks for your time, I hope you will understand my questions


You have to read the C FAQ by Steve Summit on Arrays and Pointers for
clarity on "pointers to arrays". I dont have the link handy though..


 
Reply With Quote
 
army1987
Guest
Posts: n/a
 
      12-27-2007
DiAvOl wrote:

> I perfectly understand what you are saying. I'll try to describe my
> question better.

You should quote relevant parts of the post you're replying to, to make
context clear.
> Suppose I am the C compiler and I see the following constructs:
>
> 1) printf("%d", *p); // p is an int pointer
>
> I should fetch the address which p contains and find an int value
> there.
>
> All fine with this one

Right.
> 2)
> Having:
>
> int array2d[2][2] = { {1,2} , {3,4} };
>
> &array2d = 0xbfd9e880 array2d = 0xbfd9e880 *array2d = 0xbfd9e880
>
> I (the compiler) see the construct: printf("%p", *array2d); .
>
> I should fetch the address which array2d contains (0xbfd9e880) and
> find an int pointer there. This returns 0xbfd9e880, so the address
> 0xbfd9e880 contains the int pointer 0xbfd9e880.
>
> Then I see the construct: printf("%d", **array2d);
>
> I should fetch the address which *array2d contains (0xbfd9e880 as we
> saw above) and find an int value there
>
> But I saw before that 0xbfd9e880 contains the int pointer 0xbfd9e880
> not an int number... I am confused


A pointer corresponds both to an address and a type. The type determines
how much stuff the address refers to, and how to interpret it.
Supposing an int is four bytes:
+-----------+
|00 00 00 01| 0xbfd9e880
+-----------+
|00 00 00 02| 0xbfd9e884
+-----------+
|00 00 00 03| 0xbfd9e888
+-----------+
|00 00 00 04| 0xbfd9e88c
+-----------+

Now the object declared `int array2d[2][2] = { {1,2} , {3,4} };` is an
array of arrays of ints, and spans 16 bytes. Thus, &array2d has type
"pointer to array of two arrays of two ints", and value 0xbfd9e880. Now,
an array, when is not used as the operand of & (or sizeof, or, in the case
of a string literal, as the initializer of an array of char), evaluates to
a pointer to its first element. Now, the first element of array2d is still
an array, but this time it is an array of ints.
So, array2d evaluates to &array2d[0], which is a pointer equal to &array2d,
except for its type: the former is a pointer to array of arrays of ints,
whereas the latter is a pointer to array of ints.
Now, *array2d what &array2d[0] points to, that is an array of two ints
starting at 0xbfd9e880. Since it is itself an array, it evaluates to a
pointer to its first element. This pointer still has value 0xbfd9e880, but
its type is pointer to int. Dereference it another time and you get the
int contained at that location, i.e. 1.

Resuming: &array2d, array2d, and *array2d all are (or evaluate to)
pointers to objects starting at that address. But the first points to the
whole 2d array (16 bytes), the second points to its first row (8 bytes),
and the third points to its first element (4 bytes, the int 1).
I hope I've been clear.

Nitpick: printf expects "%p" to correspond a pointer to void, that is a
pointer with no type information. You can convert a pointer of another
type to a pointer to void with a cast:
printf("%p\n", (void *)&array2d);
On most modern machines this makes no difference, as all pointers are the
same size. But on older machines pointers to void are larger, so on those
printf("%p\n", &array2d);
tries to read more data it was passed to. According to the C standard, the
latter has undefined behavior, that is the standard allows a program with
it to behave whatever the implementation likes most. Even if nowadays that
is almost always the same thing as the former, the cost of adding the cast
to be safe is so low that there is no reason not to do that.

--
Army1987 (Replace "NOSPAM" with "email")
 
Reply With Quote
 
murali.marimekala@gmail.com
Guest
Posts: n/a
 
      12-27-2007
On Dec 27, 10:54 pm, army1987 <(E-Mail Removed)> wrote:
> DiAvOl wrote:
> > I perfectly understand what you are saying. I'll try to describe my
> > question better.

>
> You should quote relevant parts of the post you're replying to, to make
> context clear.
>
>
>
> > Suppose I am the C compiler and I see the following constructs:

>
> > 1) printf("%d", *p); // p is an int pointer

>
> > I should fetch the address which p contains and find an int value
> > there.

>
> > All fine with this one

> Right.
> > 2)
> > Having:

>
> > int array2d[2][2] = { {1,2} , {3,4} };

>
> > &array2d = 0xbfd9e880 array2d = 0xbfd9e880 *array2d = 0xbfd9e880

>
> > I (the compiler) see the construct: printf("%p", *array2d); .

>
> > I should fetch the address which array2d contains (0xbfd9e880) and
> > find an int pointer there. This returns 0xbfd9e880, so the address
> > 0xbfd9e880 contains the int pointer 0xbfd9e880.

>
> > Then I see the construct: printf("%d", **array2d);

>
> > I should fetch the address which *array2d contains (0xbfd9e880 as we
> > saw above) and find an int value there

>
> > But I saw before that 0xbfd9e880 contains the int pointer 0xbfd9e880
> > not an int number... I am confused

>
> A pointer corresponds both to an address and a type. The type determines
> how much stuff the address refers to, and how to interpret it.
> Supposing an int is four bytes:
> +-----------+
> |00 00 00 01| 0xbfd9e880
> +-----------+
> |00 00 00 02| 0xbfd9e884
> +-----------+
> |00 00 00 03| 0xbfd9e888
> +-----------+
> |00 00 00 04| 0xbfd9e88c
> +-----------+
>
> Now the object declared `int array2d[2][2] = { {1,2} , {3,4} };` is an
> array of arrays of ints, and spans 16 bytes. Thus, &array2d has type
> "pointer to array of two arrays of two ints", and value 0xbfd9e880. Now,
> an array, when is not used as the operand of & (or sizeof, or, in the case
> of a string literal, as the initializer of an array of char), evaluates to
> a pointer to its first element. Now, the first element of array2d is still
> an array, but this time it is an array of ints.
> So, array2d evaluates to &array2d[0], which is a pointer equal to &array2d,
> except for its type: the former is a pointer to array of arrays of ints,
> whereas the latter is a pointer to array of ints.
> Now, *array2d what &array2d[0] points to, that is an array of two ints
> starting at 0xbfd9e880. Since it is itself an array, it evaluates to a
> pointer to its first element. This pointer still has value 0xbfd9e880, but
> its type is pointer to int. Dereference it another time and you get the
> int contained at that location, i.e. 1.
>
> Resuming: &array2d, array2d, and *array2d all are (or evaluate to)
> pointers to objects starting at that address. But the first points to the
> whole 2d array (16 bytes), the second points to its first row (8 bytes),
> and the third points to its first element (4 bytes, the int 1).
> I hope I've been clear.
>
> Nitpick: printf expects "%p" to correspond a pointer to void, that is a
> pointer with no type information. You can convert a pointer of another
> type to a pointer to void with a cast:
> printf("%p\n", (void *)&array2d);
> On most modern machines this makes no difference, as all pointers are the
> same size. But on older machines pointers to void are larger, so on those
> printf("%p\n", &array2d);
> tries to read more data it was passed to. According to the C standard, the
> latter has undefined behavior, that is the standard allows a program with
> it to behave whatever the implementation likes most. Even if nowadays that
> is almost always the same thing as the former, the cost of adding the cast
> to be safe is so low that there is no reason not to do that.
>
> --
> Army1987 (Replace "NOSPAM" with "email")


Hi ,

I just want to give a small clue to make you understand your problem.

Since, array2d is an double dimension array, If you want to access
array2d you need to deference it double time.
If you deference it once you will get the address.

Its just a clue for you. I hope you can easily analyse the problem.

bye
MMK
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointers, pointers, pointers... cerr C Programming 12 04-07-2011 11:17 PM
casting pointers/arrays to multidimensional arrays Francesco C++ 2 11-06-2009 09:04 AM
Multidimensional arrays and arrays of arrays Philipp Java 21 01-20-2009 08:33 AM
Learning pointers and arrays of pointers With Files ketema@gmail.com C Programming 1 03-28-2005 03:51 AM
Arrays and Pointers to Arrays kelvSYC C Programming 2 09-26-2003 06:52 AM



Advertisments