C++ 指向数组的指针和指向数组第一个元素的指针之间的差异

C++ 指向数组的指针和指向数组第一个元素的指针之间的差异,c++,arrays,pointers,C++,Arrays,Pointers,int(*arr)[5]表示arr是指向5个整数数组的指针。这个指针到底是什么 如果我声明int-arr[5]其中arr是指向第一个元素的指针,这是否相同 两个示例中的arr是否相同?如果不是,那么指向数组的指针到底是什么?指向数组的指针是指向特定类型数组的指针。类型包括元素的类型以及大小。不能为其分配不同类型的数组: int (*arr)[5]; int a[5]; arr = &a; // OK int b[42]; arr = &b; // ERROR: b is not

int(*arr)[5]
表示
arr
是指向5个整数数组的指针。这个指针到底是什么

如果我声明
int-arr[5]
其中
arr
是指向第一个元素的指针,这是否相同


两个示例中的
arr
是否相同?如果不是,那么指向数组的指针到底是什么?

指向数组的指针是指向特定类型数组的指针。类型包括元素的类型以及大小。不能为其分配不同类型的数组:

int (*arr)[5]; 
int a[5];
arr = &a; // OK
int b[42];
arr = &b; // ERROR: b is not of type int[5].
指向数组第一个元素的指针可以指向任何具有正确元素类型的数组的开头(实际上,它可以指向数组中的任何元素):

<>注意,在C和C++中,数组在某些上下文中会退化为指向元素的类型。这就是为什么可以这样做:

int* arr; 
int a[5];
arr = a; // OK, a decays to int*, points to &a[0]

在这里,
arr
int*
)的类型与
a
int[5]
)的类型不同,但是
a
衰减为指向其第一个元素的
int*
,使赋值合法。

如果写入
int-arr[5]
,则在堆栈上创建一个五个
int
数组。这占用的大小等于五个整数的大小

如果您写入
int(*arr)[5]
,您将创建一个指向堆栈上五个
int
数组的指针。这占用的大小等于指针的大小

如果从上面看不清楚,则指针具有与数组分离的存储,可以指向任何对象,但不能将数组名称指定给指向其他对象


<> P> >我的答案更多。

< P>整个数组的地址和第一个元素的地址定义为相同,因为C++和(C)中的数组除了组成对象之外没有固有填充。 但是,这些指针的类型是不同的。在您执行某种类型的类型转换之前,将
int*
int(*)[5]
进行比较是非常困难的

如果声明
arr[5]
,则
arr
不是指向第一个元素的指针。它是数组对象。您可以观察到这一点,因为
sizeof(arr)
将等于
5*sizeof(int)
。数组对象隐式转换为指向其第一个元素的指针


指向数组的指针不会隐式转换为任何内容,这可能是造成混淆的另一个原因。

指向数组的指针和指向数组第一个元素的指针都是不同的。在
int(*arr)[5]
的情况下,
arr
是指向
5
int
的内存块的指针。取消引用
arr
将给出整行。在
int-arr[5]
的情况下,
arr
衰减到指向第一个元素的指针。取消对arr的引用将给出第一个元素。
在这两种情况下,起始地址相同,但两个指针的类型不同

如果我声明
int-arr[5]
其中
arr
是指向第一个元素的指针,这是否相同?两个示例中的
arr
是否相同?如果不是,那么指向数组的指针到底是什么

否。要了解这一点,请参见功能图1

所有三个指针当然都允许您在
矩阵[0][0]
中定位
0
,如果您将这些指针转换为“字节地址”,并在
printf()
中使用
%p
指令打印出来,这三个指针很可能产生相同的输出(在典型的现代计算机上)。但是
int*
指针
p1
,只指向一个
int
,如黑色圆圈所示。红色指针
p2
,其类型为
int(*)[2]
,指向两个
int
s,蓝色指针——指向整个矩阵的指针——确实指向整个矩阵。 这些差异影响指针算术和一元
*
(间接)运算符的结果。由于
p1
指向一个
int
p1+1
向前移动一个
int
。黑色圆圈只有一个
int
,并且
*(p1+1)
只是下一个int,其值为1。同样,
sizeof*p1
只是
sizeof(int)
(可能是4)

由于
p2
指向一个完整的“int数组2”,因此
p2+1
将向前移动一个这样的数组。结果将是指向围绕
{2,3}
对的红色圆圈的指针。由于间接运算符的结果是一个对象,
*(p2+1)
是可能属于该规则的整个数组对象。如果它确实属于该规则,则该对象将成为指向其第一个元素的指针,即当前持有
2
int
。如果它不属于该规则,例如,in
sizeof*(p2+1)
,它将对象放在对象上下文中——它将保持整个数组对象。这意味着
sizeof*(p2+1)
(当然还有
sizeof*p2
)是
sizeof(int[2])
(可能是8)


1以上内容取自。

理论 首先是一些理论(你可以跳到“答案”部分,但我建议你也读一下):

这是一个数组,“arr”不是指向数组第一个元素的指针。在特定情况下(即将它们作为左值传递给函数),它们会衰减为指针。:您将失去对它们调用
sizeof
的能力

在正常情况下,数组是数组,指针是指针,它们是两个完全不同的东西

<
int* arr; 
int a[5];
arr = a; // OK, a decays to int*, points to &a[0]
void f(void) {
    int matrix[4][2] = { {0,1}, {2,3}, {4,5}, {6,7} };
    char s[] = "abc";
    int i = 123;
    int *p1 = &matrix[0][0];
    int (*p2)[2] = &matrix[0];
    int (*p3)[4][2] = &matrix;
    /* code goes here */
}
int arr[5]
int array1[2][2] = {{0, 1}, {2, 3}};
void function1(int **a);
void function1(int a[][2]);
void function1(int a[2][2]);
int (*arr)[5]
int arr[5]
int* ptrToArr = arr;
int (*arr)[5]
int* ptrToArr = arr; // NOT ALLOWED

Error cannot convert ‘int (*)[5]’ to ‘int*’ in initialization
int theArray[5];
int (*ptrToArray)[5];
ptrToArray = &theArray;    // OK
int anotherArray[10];
int (*ptrToArray)[5];
ptrToArray = &anotherArray;    // ERROR!
int theArray[5];
int* ptrToElement = &theArray[0];  // OK - Pointer-to element 0
int anotherArray[10];
int* ptrToElement = &anotherArray[0];   // Also OK!