1

I have read several topics about pointer in websites and PDF in the internet. But there are many things that I can't understand very clearly up till now:

In a PDF it was writen that a two dimensional array which has 10 rows and 20 columns can be declared as int (*ary)[20] instead of int array[10][20]

They explain:

"ary is defined to be a pointer to a group of contiguous, single-dimensional, 20-element integer arrays."

In many websites on the internet they just say that int (*ary)[20] is the declaration for the pointer which points to an array of 20 integers.

Gerhardh
  • 11,688
  • 4
  • 17
  • 39
Alex
  • 13
  • 2
  • 2
    This is also a very good question/answer set, especially regarding dynamic allocation of arrays in C: https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays?noredirect=1&lq=1 – Andrew Henle Aug 24 '18 at 13:29
  • 1
    Looks like you shouldn't trust the contents of that PDF. – molbdnilo Aug 24 '18 at 13:30
  • Thank you for replying . To molbdnilo : because array is not a pointer right ? – Alex Aug 24 '18 at 13:39
  • 1
    Right. An array is not a pointer. And learning the actual relationship between arrays and pointers is one of the trickiest things about learning C. (But once you get it, it's very useful.) – Steve Summit Aug 24 '18 at 13:43
  • [This webpage](https://www.eskimo.com/~scs/cclass/notes/sx10e.html) might be useful. – Steve Summit Aug 24 '18 at 13:45
  • 1
    *a two dimensional array which has 10 rows and 20 columns can be declared as `int (*ary)[20]` instead of `int array[10][20]`* No, it can't. Read the many answers as to why that's wrong. The main difference is `int array[10][20]` actually **is** an array - with memory allocated. `int (*ary)[20]` is a *pointer* that can point anywhere. It can point to an array and be used to access it, or it can point to an invalid address. Declaring that pointer doesn't create nor allocate storage for an actual array. (Posted as a comment to get it up front.) – Andrew Henle Aug 24 '18 at 13:47

5 Answers5

3

int array[10][20] is an array with 10 items, each item is an array of 20 integers. Or if you will: it is a 2D array of 10x20 int.

int (*ptr)[20] is an array pointer to an array of 20 integers. It does not allocate any memory for the array, but it can point at one.

If you write

int array[10][20];
int (*ptr)[20] = array;

then array "decays" into a pointer to the first element. The first element of int [10][20] is an int[20]. And int (*ptr)[20] is a pointer to such an element, so this is fine.

You may be confusing this for allocating a 2D array dynamically, which can be done like this:

int (*ptr)[20] = malloc( sizeof(int[10][20]) );

Here, ptr points at the first element (an int[20]) of an int[10][20] array.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

The declarations

int (*ary)[20];

and

int ary[10][20];

are very different. The first do indeed declare a pointer to an array of 20 int elements. The second declares an array of 10 arrays of 20 int elements.


The thing you have to remember is that an array naturally decays to a pointer to its first element.

For a simple array like

int simple_array[10];

then using plain simple_array in expression is the same as &simple_array[0], and the type of the expression is int *.

Now for an array of arrays

int complex_array[10][20];

if you use complex_array in an expression it's still results in a pointer to it's first element, i.e. &complex_array[0]. The difference now is the type of the expression: &complex_array[0] (or the plain equivalent complex_array) is int (*)[20].

With this information you can easily create a pointer to complex_array and make it point to the first element of complex_array:

int (*complex_array_pointer)[20];

// Make complex_array_pointer point to the first element of complex_array
// i.e. make complex_array_pointer point to complex_array[0]
complex_array_pointer = complex_array;
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

The main thing is to understand that C don't have anything else than 1-dimensional arrays. Yes, 2D arrays (e.g. matrixes) don't really exist in C.

However, an array have elements, all of the same byte size (as given by sizeof) and type. So you can have arrays of numbers, arrays of pointers, arrays of struct-s, and even arrays of arrays (e.g. of integers).

So by abuse, you could say that an array of arrays is a matrix (so some people claim that 2D arrays exist in C. I feel it is an exaggeration). But it (e.g. something declared like int a[10][20];) really stays a 1D array (of 10 elements each being an array) of 1D arrays (of 20 integers). And in many cases, an array of pointers is useful (e.g. arrays of "strings").

An interesting feature in C99 (or later) is flexible array members. With that, you could define cleverly your own Matrix abstract data type, used as an opaque pointer (see this answer for some code).

In many cases (notably when you assign an array -on the right of an assignment- to some lvalue like a variable, or pass an array as an argument to some function), arrays decay into pointers. But their sizeof and type are different.

Look into some C reference site (and much later, into the n1570 C standard, e.g. its §6.5.2.1 Array subscripting). Read How to debug small programs

BTW, so-called 2D arrays in C like int a[10][20]; are rarely needed in C (unless you specialize into numerical computations on matrixes of fixed dimensions known at compile-time; I guess that game developers might use a type like typedef double transform3Dmatrix_ty[3][3]; quite often). In more than 30 years of programming experience, I almost never used 2D arrays.

I don't pretend to teach you C in a few paragraphs. You'll find many good books (and some very bad ones).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thanks a lot for your answer but i can ask one more question that : Second is a part of first .What i mean is second statement is one of many 1-D array in the 2D array . – Alex Aug 24 '18 at 13:26
  • *The main thing is to understand that C don't have anything else than 1-dimensional arrays.* I'd say that's more of an under-the-covers implementation detail. [**6.5.2.1 Array subscripting**](https://port70.net/~nsz/c/c11/n1570.html#6.5.2.1) does mention "multidimensional array objects" and then does describe how they are really 1-dimensional, but I think a bit more explanation is in order, as the blanket statement "C don't have anything else than 1-dimensional arrays." likely confuses inexperienced C users. – Andrew Henle Aug 24 '18 at 13:38
  • 1
    Are you sure it *confuses* them? – Basile Starynkevitch Aug 24 '18 at 13:39
  • Given some of the questions that get posted here? I'm sure there are more than a few confused. And some much worse... ;-) – Andrew Henle Aug 24 '18 at 13:41
1

These are arrays:

int a[10];
int b[10][20];

These are pointers:

int *p1;
int (*p2)[20];

They are different. They are not the same.

However, even though they're different, you can do this:

p1 = a;
p2 = b;

Now p1 points at a, and p2 points at b.

When you said p1 = a it was shorthand. It was as if you had written

p1 = &a[0];

Strictly speaking, p1 points to the first element of a. Similarly, p2 = b is like p2 = &b[0] and makes p2 point at the first element of b. However, since b is an array of arrays, the first element of b is an array of 20 ints.

Also, if you pass a and b to a function, like this:

f(a, b);

what should the definition of the function look like? It turns out there are two ways to look at it. You can declare

void f(int a[], int b[20][]) { ... }

which makes f's parameters look like what you think you're passing. But it turns out it's actually pointers that get passed, so f can also be declared like this:

void f(int *a, int (*b)[20]) { ... }

Anyway, this is why that page you read suggested that there was some kind of equivalence between the array int a[10][20] and the pointer int (*p2)[20]. There is "some kind of equivalence", but it doesn't mean that they're the same type. (Not at all. For this reason, most people prefer not to use the word "equivalence" in this context any more.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
-1

You just have to consider that ary is a pointer toward its first element. Mind that the syntax ary[index] is equivalent than *(ary + index), it will help you understand how it works.

  • 2
    There are contexts where an array *decays into* a pointer to its first element, but the array itself is not a pointer. – molbdnilo Aug 24 '18 at 13:32
  • 1
    What you're trying to say is that when you use `ary` in an expression, what you get is a pointer towards its first element. But the array itself is not a pointer -- the array itself **is** an array. – Steve Summit Aug 24 '18 at 13:42
  • `int main(int argc, int **argv)` `int main(int argc, int *argv[])` `int main(int argc, int argv[][])` Then can you explain why these 3 syntaxes are actually frequently used ? – L. Chaumartin Aug 24 '18 at 13:43
  • Note that "equivalent" does not mean "exactly the same" - the syntaxes produce the same value, but `*(ary + index)` involves an implicit conversion into `*(&ary[0] + index)`. – molbdnilo Aug 24 '18 at 13:44
  • @L.Chaumartin Those `argv`s are equivalent, but none of them is an array. In a parameter type, `[]` denotes a pointer, not an array. It's a typograhical hint to the (human) reader that the parameter points to the first element of an array. You can't pass arrays to functions in C. – molbdnilo Aug 24 '18 at 13:48
  • @L.Chaumartin Now you're talking about function parameters. Yes, as function parameters, they're the same -- sort of. Actually they're still not the same, because you can't pass an array to a function. The compiler knows that the function will always receive a pointer, so if you try to declare a function parameter as an array, the compiler quietly gives you a pointer instead. – Steve Summit Aug 24 '18 at 13:48
  • 2
    @L.Chaumartin See [here](http://c-faq.com/aryptr/aryptr2.html) and [here](http://c-faq.com/aryptr/aryptrparam.html). – Steve Summit Aug 24 '18 at 13:51
  • Thank you for the explainations, I see clear right now. – L. Chaumartin Aug 24 '18 at 14:06