layout of arrays

A

AC

I noticed that if I declared an array a as
int a[2][3][1], sizeof a is 6 * sizeof(int).

This means that a occupies 6*sizeof(int) consecutive bytes, right? So I can
consider, (int *) &a as a pointer to an array of 2*3*1=6 ints. Is this
correct?

This code works fine for me :

#include <stdio.h>

int
main(void)
{
int a[2][3][1]={1,2,3,4,5,6};
int *p;
int i;
printf("sizeof a =%u\n",(unsigned int) sizeof a);
p = (int *) &a;
for(i=0; i < sizeof a/sizeof(int);i++)
printf("p[%d]=%d\n",i,p);
return 0;
}
 
M

Malcolm

AC said:
I noticed that if I declared an array a as
int a[2][3][1], sizeof a is 6 * sizeof(int).

This means that a occupies 6*sizeof(int) consecutive bytes, right? So I
can consider, (int *) &a as a pointer to an array of 2*3*1=6 ints. Is
this correct?
Yes, but be warned that everything gets horrible as soon as you try to use
such arrays in non-trivial ways.
Generally if you need a 3d array, consider whether the dimensions are really
fixed at compile time. The consider whether it makes sense to write your
subroutines so that they can only operate on an array of fixed dimensions.
If the answers to these questions are no, you will save yourself a lot of
grief by building the array with calls to malloc().
 
C

CBFalconer

AC said:
I noticed that if I declared an array a as
int a[2][3][1], sizeof a is 6 * sizeof(int).

This means that a occupies 6*sizeof(int) consecutive bytes, right?
So I can consider, (int *) &a as a pointer to an array of 2*3*1=6
ints. Is this correct?

This code works fine for me :

#include <stdio.h>

int
main(void)
{
int a[2][3][1]={1,2,3,4,5,6};
int *p;
int i;
printf("sizeof a =%u\n",(unsigned int) sizeof a);
p = (int *) &a;
for(i=0; i < sizeof a/sizeof(int);i++)
printf("p[%d]=%d\n",i,p);
return 0;
}


Looks fine to me. You might want to try this modification, playing
with the various *DIM defines, to see the correspondence of the
linear array and the multidimensional array. C only has a single
array dimension, and multidimensional arrays simply are a mapping
into a single dimensional array. Notice How I have intermixed
array and pointer notation.

Keep the dimensions below 10 so the displays show all coordinates.

#include <stdio.h>

#define XDIM 4
#define YDIM 3
#define ZDIM 2

#define LINEMAX 72

void dump(int a[][YDIM][ZDIM], size_t sz)
{
int linesize;
size_t ix;
int *p;

p = (int *)a;
linesize = 0;
for (linesize = 0, ix = 0; ix < sz; ix++) {
linesize += printf("p[%2d]=%0.3d", (int)ix, p[ix]);
if (linesize <= LINEMAX) {
putchar(' '); linesize++;
}
else {
putchar('\n'); linesize = 0;
}
}
if (linesize) putchar('\n');
} /* dump */

/* -------------------- */

void inita(int a[][YDIM][ZDIM])
{
int x, y, z;
size_t ix;
int *p;

p = (int *)&a;
for (x = 0; x < XDIM; x++)
for (y = 0; y < YDIM; y++)
for (z = 0; z < ZDIM; z++) {
ix = (((z * ZDIM) + y) * YDIM) + x;
a[x][y][z] = ((z * 10 + y) * 10) + x;
}
} /* inita */

/* -------------------- */

int main(void)
{
int a[XDIM][YDIM][ZDIM] = {1,2,3,4,5,6};
int *p;
size_t ix;

printf("sizeof a = %lu\n", (unsigned long) sizeof a);
p = (int *) &a;
for (ix = 0; ix < sizeof a/sizeof(int); ix++)
printf("p[%d]=%d\n", (int)ix, p[ix]);
dump(a, sizeof a/sizeof(int));
inita(a);
dump(a, sizeof a/sizeof(int));
return 0;
}
 
D

Dave Thompson

I noticed that if I declared an array a as
int a[2][3][1], sizeof a is 6 * sizeof(int).

This means that a occupies 6*sizeof(int) consecutive bytes, right? So I can
consider, (int *) &a as a pointer to an array of 2*3*1=6 ints. Is this
correct?
In practice but not quite 100% formally. It is clearly required by the
standard that the storage (representation) of an array be the elements
in order without additional padding, and for multidim arrays applying
this rule repeatedly requires row-major order. ("additional" because
there can be padding _within_ a struct (or union) element, including
at its end for alignment.)

It is not clearly required that you can _access_ the "flattened"
elements by a non-character pointer so ( (int*)&a ) [4] isn't itself
guaranteed. But it is required that a character pointer step through
the entire representation, so * (int*) ( (char*)&a + 4*sizeof(int) )
must. In practice, there's no reasonable way to implement the latter
without implementing the former, not to mention that it just "makes
sense" anyway, and everyone does. I think I recall a couple of
committee members commenting on comp.std.c that they intended this,
but couldn't find words they were certain adequately specified C's
historically loose memory model without risking possible problems in
other areas and let the sleeping dog lie. Especially since enough
programs and programmers do this that any implementor who broke it,
even if they could argue that they weren't violating the standard,
would be shunned by most if not all users.

- David.Thompson1 at worldnet.att.net
 

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,795
Messages
2,569,643
Members
45,356
Latest member
deepthi.kodakandla

Latest Threads

Top