Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are two dimensional arrays in C required to make all elements contiguous?

Tags:

arrays

c

I heard from a friend that two dimensional arrays in C are only supported syntactically.

He told me to better use float arr[M * N] instead of float[M][N] because C compilers like the gcc can't guarantee that on every system/platform the data lies in series within the memory.

I want to use this as an argument in my master thesis but I don't have any referrence.

So first question:

Is that right what he's saying?

Second question:

Do you know if there is a book or an article where to find this statement?

Thanks + Regards

like image 805
unlimited101 Avatar asked Jun 15 '13 16:06

unlimited101


People also ask

Are 2D arrays contiguous in C?

Yes they are contiguous.

Are arrays contiguous in C?

An array is a contiguous collection of homogeneous elements that can be accessed using an index. By contiguous, we mean the elements of the array are adjacent to one another in memory with no gaps between them. By homogeneous, we mean they are all of the same type.

What are the rules used to declare a two-dimensional array?

Any 2-dimensional array can be declared as follows: Syntax: data_type array_name[][]; (OR) data_type[][] array_name; data_type: Since Java is a statically-typed language (i.e. it expects its variables to be declared before they can be assigned values).

Why do we use two-dimensional array in C?

The 2D array is organized as matrices which can be represented as the collection of rows and columns. However, 2D arrays are created to implement a relational database lookalike data structure. It provides ease of holding the bulk of data at once which can be passed to any number of functions wherever required.


2 Answers

  1. No, he's wrong.

  2. Look at the C standard. Some relevant bits (bold emphasis mine):

    6.2.5 Types ¶20

    An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.

    6.7.6.2 Array declarators ¶3 (note 142)

    When several "array of" specifications are adjacent, a multidimensional array is declared.

    6.5.2.1 Array subscripting ¶3

    Successive subscript operators designate an element of a multidimensional array object. ... It follows from this that arrays are stored in row-major order (last subscript varies fastest).

    And perhaps most explicitly, the example in 6.5.2.1 Array subscripting ¶4:

    EXAMPLE Consider the array object defined by the declaration

    int x[3][5];

    Here x is a 3 × 5 array of ints; more precisely, x is an array of three element objects, each of which is an array of five ints. In the expression x[i], which is equivalent to (*((x)+(i))), x is first converted to a pointer to the initial array of five ints. Then i is adjusted according to the type of x, which conceptually entails multiplying i by the size of the object to which the pointer points, namely an array of five int objects. The results are added and indirection is applied to yield an array of five ints. When used in the expression x[i][j], that array is in turn converted to a pointer to the first of the ints, so x[i][j] yields an int.

Multidimensional arrays in C are just "arrays of arrays". They work fine and are 100% defined by the standard.

You may also find it helpful to read Section 6, Arrays and Pointers in the comp.lang.c FAQ.

like image 91
Carl Norum Avatar answered Sep 28 '22 02:09

Carl Norum


The issue is a bit more subtle than the other answers make it sound:

While multi-dimensional arrays are (semantically, possibly not physically) contiguous, pointer arithmetics is only defined if you stay within the bounds of the array your pointer originally referenced (actually, you can go 1 element past the upper bound, but only if you don't dereference).

This means that language semantics forbid walking through a multi-dimensional array from start to end, and a bounds-checking implementation of the C language (which are possible in principle but rarely seen in the wild for performance reasons) could raise a segfault, print a diagnostic or make demons fly from your nose whenever you cross a sub-array's boundary.

I'm not sure if compilers use this information for optimization purposes, but in principle, they could. For example, if you have

float *p = &arr[2][3];
float *q = &arr[5][9];

then p + x and q + y should never alias, regardless of the values of x and y.

like image 45
Christoph Avatar answered Sep 28 '22 02:09

Christoph