简体   繁体   中英

2-Dimensional array in memory in ANSI C

I've read many people here and in other websites saying that if a declare something like this:

double a[5][2];

it will be allocated in memory like a contiguous block like:

a[0][0] | a[0][1] | a[1][0] | a[1][1] | ....etc

But is this always a rule? I would like to create a function to multiply matrices of variable sizes but in pure CI won't be able to pass matrices by parameters without knowing at least one dimension. So I've made this:

void MatMult(double* m1, double* m2, double* res, int h, int w, int l)
{
  int i, j, k;
  for (i = 0; i < h; i++)
  {
    for (j = 0; j < w; j++)
    {
        double p_res = 0;
        for (k = 0; k < l; k++)
        {
            p_res += (*(m1+i*l+k))*(*(m2+k*w+j));
        }
        *(res+i*w+j)=p_res;
    }
  }
}

with call:

 double m1[2][3], m2[3][1], m3[2][1];
 ...
 MatMult(&(m1[0][0]),&(m2[0][0]),&(m3[0][0]),2,1,3);

And it worked. But will this always work or there are exceptions that I should be aware of like memory aligment or something like this?

To pass 2D arrays to functions you'd have to change your interface

void MatMult(size_t h, size_t w, size_t l. double m1[h][w], double m2[w][l], double res[h][l]);

or similar:

  • have the sizes first
  • then use them to declare the dimensions

Also, I have used size_t , here, since this is the correct type for all index calculations.

This should work for all compilers that implement C99. (Basically all do but Microsoft.)

Yes it will always work. Arrays declared like you did ara guaranteed to be "contiguous" which means that their items will be tightly packed up. So, if you declare double[55] you know that always the [50] -th element will come right after [49] -th element with no perceivable gaps.

I think, but I'm not perfectly sure, that for some very uncommon data types (like including unbalanced bitfields, etc), the "alignment" can still kick in and offset something. I'm not sure. But even if (see Jens comment) If the compiler adds some alignment offsets, it will do so either inside a single data element, or at the boudary between elements, and in both cases the compiler will know about it. So, it should apply all required corrections at every [], ->, . operation, as long as it still has all the required type information (array-of-doubles). If you erase the type information and start accessing the array by "untyped" (or wrong-typed) pointers, for example:

double array[50];
char* p = (char*)array;
int size = sizeof(double);
for(i=0;i<50;++i)
    .. *(double*)(p+size) ..

then of course the compiler will not have the type information and will be unable to apply proper alignment offsets. But if you do things as above, you probably know the risks already.

Next thing is, that there is no such thing as two-dimensional array. Neither in C nor in C++.

Array defined as double[5][2] is an array(5) of array(2) of double. CMIIW, I could swap them. Anyways, the point is that 'double' is a datatype and is an element of an higher-level 1D-array. Then, double[2] is a datatype and an element of an higher-level 1D-array, and so on.

Now, remember the 'sequential+contiguous' layout of arrays:

double            ->  DD
double[2]         -> [DD | DD]
double[5][2]      -> [ {DD:DD} | {DD:DD} | {DD:DD} | {DD:DD} | {DD:DD} ]

Since array has to be sequential and contiguous, the double[2] must layout its element as above - obvious.

However, since double[5][2] is an array, and its an array of [5] and since its elements are double[2] - it must layout its elements just in the same way. First whole element first, then second whole element, and so on.

Just like double[2] can't "split" its doubles into scattered 1-byte chunks, the double[5][2] can't split its array[2].

By using double a[5][2] , you are creating two dimensional array in stack which will always be a contiguous block of memory. On the other hand, if you try to create 2-D array on heap (ie using malloc), it is not guaranteed that you will get contiguous block of memory hence you might not be able traverse your allocated memory in a linear way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM