简体   繁体   中英

Difference between pointer to array

What is the difference between these two pointers? Both pointers are pointing to an array? Is it because the first pointer is a pointer to the first element of the array, while the other is a pointer to an array of 5 elements? What differences does this make in code?

int arr[5] = {1,2,3,4,5};
int *pointer = arr;
int (*pointer2)[5] = arr;

Your first declaration

int *pointer = arr;

declares pointer as a pointer to a single integer. In the initialization, arr decays to a pointer to its first element, so it's equivalent to

int *pointer = &arr[0];

The second one

int (*pointer2)[5] = arr;

declares pointer as a pointer to an array of 5 integers. The initialization isn't valid, because arr decays to a pointer to a single integer, not an array. You'd need to add a cast:

int (*pointer2)[5] = (int(*)[5])arr;

or take the address of the array (because the decay to pointer doesn't take place when taking the address of the array):

int (*pointer)[5] = &arr;

The different between the two pointer types becomes apparent when you perform pointer arithmetic, because pointer arithmetic is performed in increments of the size of the type it points to. pointer+1 is a pointer to arr[1] , but pointer2[1] would be a pointer to arr[5] , which doesn't exist.

The second,

int (*pointer2)[5] = arr;

is an error (constraint violation): initialization with wrong pointer type where there is no implicit conversion. It should be = &arr .

Both point to the same place, but have different types . This affects not only type checking, but pointer arithmetic and other things. For example, pointer+1 points to arr[1] , but pointer2+1 points "one past the end" of the object arr .

The need for pointer-to-array (rather than just pointer-to-element) types comes up when you work with multi-dimensional arrays. In

int matrix[3][3];

the name matrix alone decays not to a pointer to matrix[0][0] , but to a pointer to matrix[0] (an array of 3 int s representing a "row"). This is what makes multi-dimensional array indexing and pointer arithmetic work.

The most notorious difference, in terms of usability, is regarding pointer arithmetic, ie :

pointer++ will make the pointer access the second element in the array whereas pointer2++ will make the pointer access the next block of 5 int s. In your code the behavior of this latter case would be undefined since you only have one block of 5 ints.

A pointer to array of SIZE is useful when handling 2D arrays with SIZE columns as you can easily iterate through array lines with this simplified pointer arithmetic.

Basically, variables pointer and pointer2 have different types, however they'll both behave similarly, with the exceptions:

– there will be no array to pointer decay occurring for pointer2 like it does for initial arr , ie: eg:

#include <stdio.h>

int arr[5] = {1,2,3,4,5};
int *pointer = arr;
int (*pointer2)[5] = &arr;

void func(int *in_arr)
{
   printf("1st: %i, 5th: %i\n", in_arr[0], in_arr[4]);
}

int main(void)
{
    func(pointer);
    func(pointer2); /* generates a warning (in GCC) */
    func(arr);      /* works with no issues*/
}

The warning will be:

ex.c: In function ‘main’:
ex.c:9:14: warning: passing argument 1 of ‘func’ from incompatible pointer type [-Wincompatible-pointer-types]
    9 |         func(pointer2);
      |              ^~~~~~~~
      |              |
      |              int (*)[5]
ex.c:4:24: note: expected ‘int *’ but argument is of type ‘int (*)[5]’
    4 |         void func(int *in_arr)    {
      |                   ~~~~~^~~~~~

– pointer arithmetic will behave differently, pointer+1 will point at second element, while pointer2+1 will point after the array pointer2 .

IMO, the (type*)[size] pointers are quite peculiar thing in C. They'll allow, for example, to perform basically a cast to an array type , which is a quite strange thing to do in C – normally, you cannot cast anything to an array type (like.: func( (int [5]) ints_pointer ) , however with pointer -type to an array, it's possible to cast to it, so that, eg:

// same preamble as in previous example…

void func(int (*in_arr)[5]) {
   printf("1st: %i, 5th: %i\n", ((int *)in_arr)[0], 
        ((int *)in_arr)[4]);
}

int main(void) {
    /* ·•Casts•· to a ·•pointer-to-array•· type to mute warnings */
    func( (int(*)[5]) pointer );
    func( (int(*)[5]) arr );
    /* Generates no warning (in GCC) */
    func(pointer2);
}

works with no issues.

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