简体   繁体   English

指向数组的指针之间的区别

[英]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?是不是因为第一个指针是指向数组第一个元素的指针,而另一个指针是指向 5 个元素的数组的指针? 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.pointer声明为指向单个 integer 的指针。 In the initialization, arr decays to a pointer to its first element, so it's equivalent to在初始化中, arr衰减为指向它的第一个元素的指针,所以它相当于

int *pointer = &arr[0];

The second one第二个

int (*pointer2)[5] = arr;

declares pointer as a pointer to an array of 5 integers.pointer声明为指向 5 个整数数组的指针。 The initialization isn't valid, because arr decays to a pointer to a single integer, not an array.初始化无效,因为arr衰减到指向单个 integer 的指针,而不是数组。 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. pointer+1是指向arr[1]的指针,但pointer2[1]将是指向arr[5]的指针,它不存在。

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 .它应该是= &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 .例如, pointer+1指向arr[1] ,但pointer2+1指向 object arr的“末尾”。

The need for pointer-to-array (rather than just pointer-to-element) types comes up when you work with multi-dimensional arrays.当您使用多维 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").单独的名称matrix不会衰减到指向matrix[0][0]的指针,而是衰减到指向 matrix[0 matrix[0]的指针(代表“行”的 3 个int的数组)。 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. pointer++将使指针访问数组中的第二个元素,而pointer2++将使指针访问下一个 5 int块。 In your code the behavior of this latter case would be undefined since you only have one block of 5 ints.在您的代码中,后一种情况的行为将是未定义的,因为您只有一个 5 个整数块。

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.在处理具有SIZE列的 2D arrays 时,指向SIZE数组的指针很有用,因为您可以使用这种简化的指针算法轻松遍历数组行。

Basically, variables pointer and pointer2 have different types, however they'll both behave similarly, with the exceptions:基本上,变量pointerpointer2具有不同的类型,但是它们的行为相似,但有以下例外:

– there will be no array to pointer decay occurring for pointer2 like it does for initial arr , ie: eg: pointer2不会像初始arr那样发生指向指针衰减的数组,即:例如:

#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 . – 指针算法的行为会有所不同, pointer+1将指向第二个元素,而pointer2+1将指向数组pointer2之后。

IMO, the (type*)[size] pointers are quite peculiar thing in C. IMO, (type*)[size]指针在 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:例如,它们将允许基本上执行对数组类型的强制转换,这在 C 中是一件很奇怪的事情——通常,您不能将任何内容强制转换为数组类型(例如: func( (int [5]) ints_pointer ) ,但是使用指向数组的指针类型,可以对其进行强制转换,例如:

// 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.工作没有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM