简体   繁体   中英

What is the point of pointers to arrays?

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.

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.

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

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

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

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

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.

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