9

So, I was reading about pointers, and came across the concept of pointers to arrays. The thing is that a pointer to an array doesn't really seem useful at all, since instead of using a pointer to have an offset to access an array element, I could just get the element directly. However I feel as if I'm missing the reason why these can be useful.

So, in short, What is the point of pointers to arrays; How and why should they be used, and do they have any practical applications?

Edit: I meant this in the context of normal/simple arrays such as:

int array[5];

Edit: As Keith Pointed out, I'm specifically asking about pointers to arrays, for example char (*ptr)[42] which is a pointer to a 42-element array of char.

Rivasa
  • 6,510
  • 3
  • 35
  • 64
  • what kind of arrays? `int* myArray = malloc(5 * sizeof(int) );` is an array too... – LihO Oct 05 '13 at 16:12
  • @LihO, I meant simple arrays, like int array[5]; I'll edit it.. – Rivasa Oct 05 '13 at 16:14
  • 3
    Since when is 5 contiguous ints an array? – Paul Oct 05 '13 at 16:14
  • @Paulpro, that's what the first definition of an array that I have encountered. – Rivasa Oct 05 '13 at 16:16
  • What your wrote in your question is indeed an array. What @LihO said is not an array. Naming the pointer `myArray` doesn't make it an array. – Paul Oct 05 '13 at 16:18
  • [What does sizeof(&array) return?](http://stackoverflow.com/questions/15177420/what-does-sizeofarray-return/15177499#15177499) – Grijesh Chauhan Oct 05 '13 at 16:19
  • 1
    @Paulpro: Syntactically it's not an array, but semantically it is. – LihO Oct 05 '13 at 16:22
  • Not really. It's similar to an array semantically but not the same. For example the sizeof operator will return different results. – Paul Oct 05 '13 at 16:39
  • pun intended in title? – AndersK Oct 05 '13 at 18:17
  • @claptrap yea...uh totally intentional :) – Rivasa Oct 05 '13 at 18:45
  • Most of your questions related to "why...?" can be answered by Dennis Richie's history of C http://cm.bell-labs.com/who/dmr/chist.html – technosaurus Oct 05 '13 at 23:40
  • There's some confusion between pointers to arrays and pointers to elements of arrays. Your title says that you're asking about pointers to arrays, for example `char (*ptr)[42]` which is a pointer to a 42-element array of `char`. Is that your intent, or are you asking about pointer to *elements* of array, as in `char array_object[10]; char *not_an_array_pointer = array_object;`? In any case, mfxm's advice to read section 6 of the [comp.lang.c FAQ](http://www.c-faq.com/) is excellent. – Keith Thompson Oct 06 '13 at 02:03
  • 1
    @LihO: You wrote: "`int* myArray = malloc(5 * sizeof(int) );` is an array too". Yes and no. The `malloc` call, if it succeeds, allocates space for an anonymous 5-element array of `int`. But `myArray` is a pointer object, of type `int*`. `myArray` is not in any sense an array. It merely happens to point to the first element of an array. – Keith Thompson Oct 06 '13 at 02:06
  • None of the answers yet have stated the most common occurrence of pointers to arrays. Consider the expression `a[i][j]`, given the declaration `int a[3][3];`. In this expression, `a` is automatically converted to a pointer to an array of three `int`, before the first subscript operator is applied. This is necessary since the subscript operator works only on pointers, not on arrays. Thus, pointers to arrays are automatically and invisibly used in normal matrix operations. – Eric Postpischil Oct 06 '13 at 13:14
  • @KeithThompson, the formor, I'll edit it again. – Rivasa Oct 06 '13 at 14:52

6 Answers6

11

Unfortunately some answers you received show misbeliefs about pointers and arrays in C, in brief:

1) Pointer to array is not the same as pointer to first element.

2) Declaring array type is not the same as declaring pointer.

You can found full description in C faq part related to common confusion between pointers and arrays: http://c-faq.com/aryptr/index.html

Adressing your question - pointer to array is usefull to pass an entire array of compile-time known size and preserve information about its size during argument passing. It is also usefull when dealing with multi dimensional arrays when you what to operate on subarray of some array.

mfxm
  • 184
  • 4
  • Right, there are so many bogus answers, here. The only one that brings it to the point that I have seen. – Jens Gustedt Oct 05 '13 at 20:50
  • I think that the example in my answer agrees with this one. – Emanuele Paolini Oct 06 '13 at 18:24
  • @mfxm Question, since I can't seem to understand, how is a Pointer to an array different from a pointer to the first element, and is it a different way of having the code for each?? – Rivasa Oct 08 '13 at 22:22
  • @Link In breif, pointer to T array points to entire array consisting of elements of type T, while pointer to T points only to specific object of type T which may be part of array or just sole object. Probably you can better understand by comparing this issue to pointer to structure (containing several members including int) vs. pointer to int. While pointer to structure should point to entire structure, pointer to int may refer to that member of the structure, array element ot just int variable. Consider looking at C faq: http://c-faq.com/aryptr/ptrtoarray.html – mfxm Oct 09 '13 at 06:19
7

In most expressions, an object of type "array of T" will degrade to the address of the first array element, which will have the type "pointer to T". In this sense, a pointer type can be used to represent an array of items, and is used to do so when there is need to dynamically allocate an array.

// ptr used to dynamically allocate array [n] of T
T *ptr = malloc(n * sizeof(*ptr));

In the case of a pointer to an array, then, it can be used to represent an array of arrays, and/or dynamically allocate an array of arrays. So, a pointer to an array can be used to represent a 2-dimensional array.

// ptr used to dynamically allocate 2 dimensional array [n][10] of T
T (*ptr)[10] = malloc(n * sizeof(*ptr));
jxh
  • 69,070
  • 8
  • 110
  • 193
5

True pointers to arrays (which haven't really been addressed so far) are uncommon since arrays decay to a pointer to their first element in most contexts, and since arrays are contiguous in memory by definition that is usually all that is needed. They are also somewhat impractical compared to other pointer types since array types cannot be assigned to. They are similar to function pointers in that respect.

The biggest practical difference comes from the fact that they preserve the size of the array in situations where it would otherwise be lost to pointer decay, such as function calls and returns. Take the following code for example

void function(char (*array)[10]) {
    for(size_t i = 0; i < sizeof(*a); i++);
        (*a)[i] = i;
}
...
char a[10];
function(&a);

Besides allowing for this application of sizeof (which isn't terribly useful since the size is known as part of the parameter), this enforces the exact size of the passing argument as part of the type, which function(char array[10]) won't do, even with [static 10]. Returning has an unusual syntax:

char (*function(void))[10] {
    static char array[10];
    // do something with our static array
    return &array;
}
char (*a)[10] = function();
// or even
char (*b)[sizeof(*function())] = function();

I don't think I've ever come across an application of this in the wild, but it is at least possible (and legal).

tab
  • 903
  • 1
  • 6
  • 8
2

If you have an array of arrays a pointer to an array becomes useful, like in the following:

typedef float Point[3];
Point points[10];

Point *p;
for (p=points;p<points+10;++p) {
   ...
}
Emanuele Paolini
  • 9,912
  • 3
  • 38
  • 64
1

Here is real-world example of using pointers to arrays:

typedef double t_matrix33[3][3];

// Result = AB
//                  const double (* M1)[3], const double (* M2)[3], double (* Result)[3] 
void Matrix33xMatrix33( const t_matrix33 M1, const t_matrix33 M2, t_matrix33 Result ) {

    t_matrix33 copy;
    const t_matrix33 * A = ( const t_matrix33 * )M1;  // const double (* A)[3][3] = const double (* M1)[3]
    const t_matrix33 * B = ( const t_matrix33 * )M2;  // const double (* B)[3][3] = const double (* M2)[3]
    int Raw;
    int Col;
    int i;

    // !!! Make copies if Result is the same as M1 and/or M2!

    //const double (* A)[3][3] == double (* Result)[3]
    if( A == ( const t_matrix33 * )Result ) {  // cast is must -- to get rid of gcc warnings

        memcpy( copy, A, sizeof( t_matrix33 ) ); 
        A = ( const t_matrix33 * )copy;

        if( B == ( const t_matrix33 * )Result ) {
            B = ( const t_matrix33 * )copy;
        }
    }

    else if( B == ( const t_matrix33 * )Result ) {
        memcpy( copy, B, sizeof( t_matrix33 ) ); 
        B = ( const t_matrix33 * )copy;
    }

    for( Raw = 0; Raw < 3; ++Raw ) {
        for( Col = 0; Col < 3; ++Col ) {
            Result[ Raw ][ Col ] = 0;
            for( i = 0; i < 3; ++i ) {
                Result[ Raw ][ Col ] += (*A)[ Raw ][ i ] * (*B)[ i ][ Col ];
            }
        }
    }
};

Thanks to A and B pointers we can avoid redundant memcopies in the case of M1 and/or M2 are not the same as Result

kotlomoy
  • 1,420
  • 8
  • 14
-1

The one I can think of at the moment is (I am sure there are others as well), you want to make multidimensional array, however you don't have any data at the moment to save in the 2nd or 3rd dimension of the array. You don't want to waste the memory by conserving the space for 2nd and 3rd dimension of the array but you plan to allocate the memory later when you have data to store, thats when pointers to arrays come handy.

Eg.

for (int i=0; i<10; i++)
   (*x)[i] = malloc(N * sizeof(*x));


   // take input or put data in the array

Representation Of 2d Array In C:

This site explains it quite well. This should help you removing any confusions.

Umer Farooq
  • 7,356
  • 7
  • 42
  • 67
  • Just to be clear, is the first line of code declaring an array of pointers? Or is it one pointer to an array? – Rivasa Oct 05 '13 at 18:47
  • The first code including is just to show that you can represent a 2d array like that, it is one pointer to array. in second code, I am allocating memory for 2nd dimention of the array. – Umer Farooq Oct 05 '13 at 19:25
  • Okay then, but how exactly is the representation to a 2D array work? – Rivasa Oct 05 '13 at 19:42
  • well almost similar to 1d array. I can't explain it in detail in the comment section, I guess it would be better to search it on bing/google – Umer Farooq Oct 05 '13 at 20:01
  • You are not describing multidimensional arrays in your answer, but only an emulation of such a thing. – Jens Gustedt Oct 05 '13 at 20:45
  • `int *x[10];` does not declare one pointer to an array. It declares ten pointers to `int`. One pointer to an array would be `int (*x)[10];`. Regardless of which it declares, following it immediately by `*x[i] = i*2;` uses an uninitialized pointer, resulting in behavior not defined by the C standard. On top of that, in neither case would it have the type `int **` shown in the later cast from `malloc`. – Eric Postpischil Oct 06 '13 at 10:39
  • -1 Where is a pointer to array here? What is `x`? If `x` is pointer to array why we need it? We can use just array of pointers to initialize array of pointers. – kotlomoy Oct 06 '13 at 11:44