473,490 Members | 2,473 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Is the name of a 2-dimensional array equal to address of [0][0] element?

Hello,

I'm having some problems understanding 2 dimensional arrays. My
problem relates to the following code:

#include <stdio.h>

#define M 3
#define N 3

void ZeroInitArray(int **array, int m, int n); /* prototype */
int main(void)
{
int array[M][N];

int i, j;

for(i=0; i < M; i++)
{
for(j=0; j < N; j++)
{
array[i][j] = i * j;
}
}

ZeroInitArray(array, M, N);

return 0;

}
void ZeroInitArray(int **array, int m, int n)
{
int i, j;

for(i=0; i < m; i++)
{
for(j=0; j < n; j++)
{
array[i][j] = 0;
}
}
}
===END OF CODE===

Error message: My compiler reports that I am passing in an incorrect
pointer type.

I've read the FAQ on this subject, but still no enlightenment.
From what I understand, an array's name is equivalent to a pointer to

it's first element.

for example:

int x[5];

x = &x[0]; /* {pointer to first element) */
So what doesn't this apply to two dimensional arrays?

int x[5][5];

/* to me, this two dimensional array is in fact an array of arrays..
where x[0] is an array of int [5] and so is x[1], x[2] , .. , x[5]. So
x[0] would be equivalent to a pointer to the first element of it's
array.. &x[0][0]. So x[3] would be equivalent to &x[3][0]. The larger
array (that holds the subarrays) has the name x, and it would be
equivalent to the address of it's first element &x[0][0]. If this
address is sent properly to the receiving function I used, then there
should be no problem. Why is this illegal? Any insights would be
helpful */

Nov 14 '05 #1
9 2298
In article <11**********************@f14g2000cwb.googlegroups .com>
Luke Wu <Lo***********@gmail.com> wrote:
I'm having some problems understanding 2 dimensional arrays.
See the comp.lang.c FAQ, section 6 (sounds like you did already),
and/or <http://web.torek.net/torek/c/pa.html>.

[snippage]
From what I understand, an array's name is equivalent to a pointer to
its first element.
It gets *converted to* a pointer to the first element.
So what doesn't this apply to two dimensional arrays?
The trick is that C does not *have* two-dimensional arrays...
int x[5][5];

/* to me, this two dimensional array is in fact an array of arrays..
where x[0] is an array of int [5] and so is x[1], x[2] , .. , x[5]. So
x[0] would be equivalent to a pointer to the first element of it's
array..
All good so far, but here is where you go wrong:
&x[0][0].


A pointer to the first element of the array "x" is &x[0], not
&x[0][0]. See <http://web.torek.net/torek/c/pa.html>, and note
the "size of the circle" parts (in this case, compare the red and
black circles). These are determined by the types: &x[0] has type
"pointer to array 5 of int" or "int (*)[5]". This type is not
compatible with "int **", because "int **" does not point to a
5-int-wide circle; and indeed, trying to force it to fit (via a
cast, for instance) will produce code that fails at runtime, on
typical implementations.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #2
So then is this assumption wrong?:

sample[A][b][C][D]; /* assume we declared 4 dimensional matrix */

sample[a][b][c][d] == *(*(*(*(sample+d)+c)+b)+a); yes or no?
Thank you

Nov 14 '05 #3
"Luke Wu" <Lo***********@gmail.com> wrote in
<11**********************@f14g2000cwb.googlegroups .com>:
#define M 3
#define N 3
...
void ZeroInitArray(int **array, int m, int n); /* prototype */
...
int array[M][N];
...
ZeroInitArray(array, M, N);
...
Error message: My compiler reports that I am passing in an incorrect
pointer type.
Yes: you are attempting to pass a pointer to array to a function expecting a
pointer to pointer.
I've read the FAQ on this subject, but still no enlightenment.

From what I understand, an array's name is equivalent to a pointer to
it's first element.
No, an array's name refers to the array. In certain (most) situations, an
array expression "decays" to a pointer to its first element. One situation
where it doesn't is as an argument to the sizeof operator: 'sizeof array'
yields the total size of the array, not the size of a pointer to its first
element.
for example:

int x[5];

x = &x[0]; /* {pointer to first element) */

So what doesn't this apply to two dimensional arrays?

int x[5][5];
It does. However, just as an array of N int decays to a pointer to int, an
array of array of N int decays to a *pointer to array of N int*. There is no
further decay to a pointer to pointer to int. (If there were, what on earth
would it point at, remembering that the array contains ints, not pointers?)
/* to me, this two dimensional array is in fact an array of arrays..
where x[0] is an array of int [5] and so is x[1], x[2] , .. , x[5]. So
x[0] would be equivalent to a pointer to the first element of it's
array.. &x[0][0]. So x[3] would be equivalent to &x[3][0]. The larger
array (that holds the subarrays) has the name x, and it would be
equivalent to the address of it's first element &x[0][0]. If this
address is sent properly to the receiving function I used, then there
should be no problem. Why is this illegal? Any insights would be
helpful */


You're nearly there. The key is that the decay from array to pointer only
happens to the outermost array. I'd suggest reading and digesting the FAQ
entries on this again; they explain it a lot better than I can. :)

-- Mat.

Nov 14 '05 #4
Luke Wu wrote:
So then is this assumption wrong?:

sample[A][b][C][D]; /* assume we declared 4 dimensional matrix */

sample[a][b][c][d] == *(*(*(*(sample+d)+c)+b)+a); yes or no?


No.

sample[a] == *(sample + a)
sample[a][b] == *( sample[a] + b ) == *( *(sample + a) + b )
....

--
Peter

Nov 14 '05 #5
I understand now.

I think my confusion started with the fact that I didn't realize that
multidimensional arrays are in fact stored in continguous storage
elements and that the second dimension was just a way to step over
large chunks of this contiguous array. I was assuming that there was
an intermediate array (with pointers that pointed to different arrays
of the last dimension) - much like one would do with dynamically
allocated arrays using MALLOC.

My prof should have just pointed us to the FAQ associated with this
newsgroup instead of the horrid textbooks out there (Learn C in 21
seconds, etc. etc.).
Peter Nilsson wrote:
Luke Wu wrote:
So then is this assumption wrong?:

sample[A][b][C][D]; /* assume we declared 4 dimensional matrix */

sample[a][b][c][d] == *(*(*(*(sample+d)+c)+b)+a); yes or no?


No.

sample[a] == *(sample + a)
sample[a][b] == *( sample[a] + b ) == *( *(sample + a) + b )
...

--
Peter


Nov 14 '05 #6
Luke Wu wrote:

I understand now.

I think my confusion started with the fact that I didn't realize that
multidimensional arrays are in fact stored in continguous storage
elements and that the second dimension was just a way to step over
large chunks of this contiguous array. I was assuming that there was
an intermediate array (with pointers that pointed to different arrays
of the last dimension) - much like one would do with dynamically
allocated arrays using MALLOC.

My prof should have just pointed us to the FAQ associated with this
newsgroup instead of the horrid textbooks out there (Learn C in 21
seconds, etc. etc.).


There's an html C89 last draft at:
http://dev.unicals.com/papers/c89-draft.html
and an N869 at:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n869/

I recommend starting by reading "definition of terms"
and "use of the library" first.
In C89 draft that would be:
1.6 DEFINITIONS OF TERMS
4. LIBRARY
4.1 INTRODUCTION
in N869:
3. Terms and definitions
7. Library
7.1 Introduction

After that, the descriptions of the functions in the
standard library are pretty easy to read, as long as you
remember to read the introduction to the header first.
In other words, before reading N869
7.21.2.1 The memcpy function
you should first review
7.21.1 String function conventions

--
pete
Nov 14 '05 #7
On Mon, 17 Jan 2005 19:25:35 -0800, Luke Wu wrote:
I understand now.

I think my confusion started with the fact that I didn't realize that
multidimensional arrays are in fact stored in continguous storage
elements and that the second dimension was just a way to step over
large chunks of this contiguous array. I was assuming that there was
an intermediate array (with pointers that pointed to different arrays
of the last dimension) - much like one would do with dynamically
allocated arrays using MALLOC.


Both layouts can be achieved with or without using malloc(), for example
int (*p)[5] = malloc(4 * sizeof *p);

will (if malloc succeeds) create an object that we can access through p
with the same layout as

int a[4][5];

e.g. p[3][1] accesses an equivalent element to a[3][1]. The magic is in
the type, p here is a pointer to an array of 5 ints. p[3] selects a
particular sub-array of 5 ints and p[3][1] selects an int from that
subarray.

Lawrence

Nov 14 '05 #8

Lawrence Kirby wrote:
On Mon, 17 Jan 2005 19:25:35 -0800, Luke Wu wrote:
I understand now.

I think my confusion started with the fact that I didn't realize that multidimensional arrays are in fact stored in continguous storage
elements and that the second dimension was just a way to step over
large chunks of this contiguous array. I was assuming that there was an intermediate array (with pointers that pointed to different arrays of the last dimension) - much like one would do with dynamically
allocated arrays using MALLOC.
Both layouts can be achieved with or without using malloc(), for

example

int (*p)[5] = malloc(4 * sizeof *p);

will (if malloc succeeds) create an object that we can access through p with the same layout as

int a[4][5];

e.g. p[3][1] accesses an equivalent element to a[3][1]. The magic is in the type, p here is a pointer to an array of 5 ints. p[3] selects a
particular sub-array of 5 ints and p[3][1] selects an int from that
subarray.

Lawrence

So as far as the C standard is concerned, are the following true for a
multidimensional array? (i.e., int array[3][3]; )

1. array[1][2] < array [2][0]
1a. array[1][2] + 1 == array[2][0]
2. array[0][3] == array [1][0]
3. array[2] > array [1] > array [0]

I've seen some sample programs where a multidimensional array is passed
to a function, but inside the function the array is treated as a single
dimensional array to step through the elements. Is this a fair
treatment under the C standard?

===
From everyone's help, I'm coming to the realization that there are not

real multidimensional arrays in C, but only 2 types of simulated arrays
(1. contiguous elements, and 2. intermediate array with poitners to
subarrays - where traditional declaration using int array[A][b] uses
array type 1.)

Thanks everyone

Nov 14 '05 #9
On Tue, 18 Jan 2005 09:35:26 -0800, Luke Wu wrote:

Lawrence Kirby wrote:
On Mon, 17 Jan 2005 19:25:35 -0800, Luke Wu wrote:
> I understand now.
>
> I think my confusion started with the fact that I didn't realize that > multidimensional arrays are in fact stored in continguous storage
> elements and that the second dimension was just a way to step over
> large chunks of this contiguous array. I was assuming that there was > an intermediate array (with pointers that pointed to different arrays > of the last dimension) - much like one would do with dynamically
> allocated arrays using MALLOC.
Both layouts can be achieved with or without using malloc(), for

example


int (*p)[5] = malloc(4 * sizeof *p);

will (if malloc succeeds) create an object that we can access through

p
with the same layout as

int a[4][5];

e.g. p[3][1] accesses an equivalent element to a[3][1]. The magic is

in
the type, p here is a pointer to an array of 5 ints. p[3] selects a
particular sub-array of 5 ints and p[3][1] selects an int from that
subarray.

Lawrence

So as far as the C standard is concerned, are the following true for a
multidimensional array? (i.e., int array[3][3]; )


This is a subject that has been open to much debate. AS such is is best to
take a conservative view. It is important to remember that C doesn't have
multidimensional arrays as such, it has arrays whose elements can also be
arrays. There are objects within objects. So array[1] is an array of 3
ints, array[2] is different array of 3 ints, although both are contained
within array.
1. array[1][2] < array [2][0]
I'll assume for all of these that you meant to compare the addresses of
the elements.

array[1] and array[2] are different arrays and relational comparisons
compare pointers to elements of the same array. So this has undefined
behaviour.
1a. array[1][2] + 1 == array[2][0]
&array[1][2]+1 is a valid pointer for some purposes, but for boundary
reasons is not a valid pointer to array[2][0]. It is a tricky case, but
portable code should not assume that it works.
2. array[0][3] == array [1][0]
Same issues as 1a.
3. array[2] > array [1] > array [0]
That's fine, also true with array[3].
I've seen some sample programs where a multidimensional array is passed
to a function, but inside the function the array is treated as a single
dimensional array to step through the elements. Is this a fair
treatment under the C standard?


It depends on how the code does it. For example in

int *p = &array[0][0];

p should only be used to point to elements of array[0]. If you write one
of

int *p = (int *)array;
int *p = (int *)&array;

you are on safer ground. While C doesn't require a pointer to know how big
the array it is pointing into is, it is *allowed* to contain boundary
information, and operations may fail if those boundaries are violated. In
this case you want such boundary information to relate to the top level
array rather than a subarray.

Lawrence
Nov 14 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
63607
by: stewart.midwinter | last post by:
No doubt I've overlooked something obvious, but here goes: Let's say I assign a value to a var, e.g.: myPlace = 'right here' myTime = 'right now' Now let's say I want to print out the two...
2
2722
by: Ravi | last post by:
My XML looks like: <abc> <def type="apple"> 1 </def> <def type="peach"> 2 </def> <def type="orange"> 3 </def> <def type="banana"> 4 </def> <def type="plum"> 5 </def> </abc>
1
2614
by: discomiller | last post by:
Mario Mueller: Hello *, radiobuttons belong to other radiobuttons by the "name="any_value"" attribut. Thats a fakt. I got the following XML:...
12
2436
by: CJ | last post by:
Why won't this work? I am passing the name of the form (I have two that use this validation script) but I keep getting an error. Error reads: "document.which_form.name is null or not an object" ...
4
8418
by: IMS.Rushikesh | last post by:
Hi All, I am trying to execute below code but it gives me an COMException ///// Code Start //// public string GetName(Excel.Range range) { try { if (range.Name != null)
2
1467
by: Giovane Calabrese | last post by:
( aspx + vb ) hi everyone ! I really need make that function work ! im brazilian , and i want to make a multilanguage system , that function above must look at all ASPX take the labels ID and...
0
1760
by: Giovane Calabrese | last post by:
ok. im try to make a multilanguage system based on that tutorial : http://www.123aspx.com/redir.aspx?res=29112 in my aspx pages all text are in labels , and i want to take the name labels...
14
3234
by: Altman | last post by:
Ok I have a control that is inherited from another class. In the child I put msgbox(me.name) in the load event. What always pops up is the name of the parent class and not the name of the...
3
4954
by: TomislaW | last post by:
I am sending word document with e-mail from asp.net 2.0 application. I read doc file like this:FileStream fs = System.IO.File.Open(docPath,FileMode.Open,FileAccess.Read,FileShare.Read); Then...
0
7108
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7181
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
5445
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4875
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4565
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3078
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3071
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1383
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
272
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.