Alex
Alex

Reputation: 13

Several disturbance about the pointer

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.

Upvotes: 1

Views: 103

Answers (5)

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).

Upvotes: 1

L. Chaumartin
L. Chaumartin

Reputation: 54

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.

Upvotes: -1

Lundin
Lundin

Reputation: 214385

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.

Upvotes: 3

Steve Summit
Steve Summit

Reputation: 48010

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.)

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409364

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;

Upvotes: 2

Related Questions