如何获取数组指针的地址?
How to get the address of an array pointer?
我有以下c代码:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int **pp = &arr;
编译器报错,我不知道为什么。
arr 不是指向 int 数组的指针吗?我应该能够将它的地址分配给一个 int**。
还有其他方法吗?
Isn't arr a pointer points to an int array?
不,arr
根本不是指针。 arr
是一个数组。如果你取arr
的地址,你得到的是一个指向数组的指针,而不是一个指向指针的指针。这会起作用:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*pp)[8] = &arr;
// cleaner by using a type alias:
using Arr8 = int[8];
Arr8* pp = &arr;
如果你想要一个指向指针的指针,那么你必须首先创建一个你可以指向的指针:
int* p = arr; // same as = &arr[0]
int** pp = &p;
But when I do printf("arr: %x\n", arr);. It actually prints out the starting address of arr. Doesn't that mean it is a variable stores the address of the array?
不是这个意思。 arr
是数组;它不存储数组的地址,变量的类型不是指针。
当您将数组作为可变参数传递时,它将隐式转换为指向第一个元素的指针。这与上面示例中发生的隐式转换相同:int* p = arr;
.
请注意,%x
格式说明符要求参数的类型为 int
(或类似)。 int*
(隐式转换的结果类型)是错误的类型,因此程序的行为将是未定义的。
如果你有一个像
这样声明的对象
T x;
其中 T
是某种类型说明符,那么指向此类对象的指针声明将类似于
T *p = &x;
现在考虑数组
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
使用此类型 def
typedef int T[8]:
你可以像这样重写数组声明
T arr = {1, 2, 3, 4, 5, 6, 7, 8};
所以指向对象 arr
的指针声明看起来像
T *p = &arr;
由于类型说明符 T 表示类型 int[8]
,因此指向该类型对象的指针将具有类型 int ( * )[8]
.
所以上面的声明看起来像
int ( *p )[8] = &arr;
至于声明
int **pp;
那么可以通过以下方式引入
int *p = arr;
int **pp = &p;
那是在第一个声明中
int *p = arr;
数组指示符 arr
被隐式转换为指向其第一个元素的指针。所以指针p
是由数组第一个元素的地址arr
.
初始化的
反过来指针pp
由指针p
的地址初始化。
array name 本身就是 [0] index 的地址所以只需要像这样制作一个指针
int *p=array_name;
现在只需增加指针并访问数组,就像这样。
*(array_name + i) 其中 i 可以是您要访问的任何索引。
数组和指针是根本不同的东西:
将数组想象成一条有建筑物的街道:每栋建筑物都有一个编号,街道有一个名称。在定义中 int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
数组名称 arr
就像街道名称,编号为 0
到 7
的数组元素是包含每个数字的建筑物。
指针是一个包含对象地址的对象:一张写有建筑物地址的纸:char *p = &arr[1];
类似于在纸上写 1, street arr
一张纸。为方便起见,但更容易混淆,char *p = arr;
等同于 char *p = &arr[0];
就像告诉你的 GPS 去第五街会带你到那条街上的第一所房子。
一个指针指向一个指针,int **pp
是一张纸上写地方的地方,另一张纸上写着上面那段楼的地址。在某些情况下可能需要这种类型的指针,但不像常规指针那样常见。
定义int **pp = &arr;
不正确,因为&arr
不是指针的地址。它是完整数组的地址arr
,是一种特殊类型的指针,就像契约是一种描述实际属性的特殊类型的文件:街道的完整延伸arr
,包括人行道、人行道、地块和在其上竖立的建筑物。 指向完整数组的指针具有特殊语法:int (*p)[8] = &arr;
它仅用于高级 C 编程。大多数程序员永远不需要,甚至可能不理解语法,就像在现实生活中一样,属性 行为很少在律师办公室和官方场所之外看到,而且对 民众来说大多是深奥的.
为了您的目的,您可以定义一个指向 int
的指针并使其指向数组的开头: int *p = arr;
如果您真的需要一个指向指向 int
的指针,您可以将 pp
定义为 int **pp = &p;
通过pp
访问数组的第3个元素将写成(*pp)[3]
或pp[0][3]
1.
1 以及其他可读性较差的可能性:*(*pp + 3)
、*(3 + *pp)
和完全晦涩的替代方案:3[*pp]
、3[0[pp]]
。 ..
案例一
这里我们考虑语句:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
以上语句创建了一个名为 arr
的数组,大小为 8
,包含 int
个元素。数组 arr
的类型是 int [8]
.
案例二
这里我们考虑语句:
int **pp = &arr;
以上声明需要注意以下几点:
- 在左侧,我们有一个 指向名为
pp
的 int
的指针。也就是说,左边pp
的类型是int**
.
- 在右边,我们有表达式
&arr
。由于从案例1,我们知道数组arr
的类型是int [8]
。因此,&arr
是 int (*)[8]
,它被读作 指向大小为 8 且元素类型为 int
. 的数组的指针
所以基本上,左侧的类型是 int**
(来自第 1 点),而右侧的类型是 int (*)[8]
(来自第 2 点)。也就是说,左边和右边的类型不匹配。这就是编译器给我们错误提示的原因:
error: cannot convert ‘int (*)[8]’ to ‘int**’ in initialization
这意味着您正在尝试初始化 pp
,它是一个 int**
,类型为 int (*)[8]
.[=37 的 initializer =]
要解决这个你需要确保左右手边的类型匹配,如下所示:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*pp)[8] = &arr; //now the type on rhs and lhs match
现在左侧 pp
的类型是 int (*)[8]
,它与右侧 &arr
的类型匹配,因此这个程序工作正常。
我有以下c代码:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int **pp = &arr;
编译器报错,我不知道为什么。 arr 不是指向 int 数组的指针吗?我应该能够将它的地址分配给一个 int**。 还有其他方法吗?
Isn't arr a pointer points to an int array?
不,arr
根本不是指针。 arr
是一个数组。如果你取arr
的地址,你得到的是一个指向数组的指针,而不是一个指向指针的指针。这会起作用:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*pp)[8] = &arr;
// cleaner by using a type alias:
using Arr8 = int[8];
Arr8* pp = &arr;
如果你想要一个指向指针的指针,那么你必须首先创建一个你可以指向的指针:
int* p = arr; // same as = &arr[0]
int** pp = &p;
But when I do printf("arr: %x\n", arr);. It actually prints out the starting address of arr. Doesn't that mean it is a variable stores the address of the array?
不是这个意思。 arr
是数组;它不存储数组的地址,变量的类型不是指针。
当您将数组作为可变参数传递时,它将隐式转换为指向第一个元素的指针。这与上面示例中发生的隐式转换相同:int* p = arr;
.
请注意,%x
格式说明符要求参数的类型为 int
(或类似)。 int*
(隐式转换的结果类型)是错误的类型,因此程序的行为将是未定义的。
如果你有一个像
这样声明的对象T x;
其中 T
是某种类型说明符,那么指向此类对象的指针声明将类似于
T *p = &x;
现在考虑数组
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
使用此类型 def
typedef int T[8]:
你可以像这样重写数组声明
T arr = {1, 2, 3, 4, 5, 6, 7, 8};
所以指向对象 arr
的指针声明看起来像
T *p = &arr;
由于类型说明符 T 表示类型 int[8]
,因此指向该类型对象的指针将具有类型 int ( * )[8]
.
所以上面的声明看起来像
int ( *p )[8] = &arr;
至于声明
int **pp;
那么可以通过以下方式引入
int *p = arr;
int **pp = &p;
那是在第一个声明中
int *p = arr;
数组指示符 arr
被隐式转换为指向其第一个元素的指针。所以指针p
是由数组第一个元素的地址arr
.
反过来指针pp
由指针p
的地址初始化。
array name 本身就是 [0] index 的地址所以只需要像这样制作一个指针 int *p=array_name; 现在只需增加指针并访问数组,就像这样。 *(array_name + i) 其中 i 可以是您要访问的任何索引。
数组和指针是根本不同的东西:
将数组想象成一条有建筑物的街道:每栋建筑物都有一个编号,街道有一个名称。在定义中
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
数组名称arr
就像街道名称,编号为0
到7
的数组元素是包含每个数字的建筑物。指针是一个包含对象地址的对象:一张写有建筑物地址的纸:
char *p = &arr[1];
类似于在纸上写1, street arr
一张纸。为方便起见,但更容易混淆,char *p = arr;
等同于char *p = &arr[0];
就像告诉你的 GPS 去第五街会带你到那条街上的第一所房子。一个指针指向一个指针,
int **pp
是一张纸上写地方的地方,另一张纸上写着上面那段楼的地址。在某些情况下可能需要这种类型的指针,但不像常规指针那样常见。定义
int **pp = &arr;
不正确,因为&arr
不是指针的地址。它是完整数组的地址arr
,是一种特殊类型的指针,就像契约是一种描述实际属性的特殊类型的文件:街道的完整延伸arr
,包括人行道、人行道、地块和在其上竖立的建筑物。 指向完整数组的指针具有特殊语法:int (*p)[8] = &arr;
它仅用于高级 C 编程。大多数程序员永远不需要,甚至可能不理解语法,就像在现实生活中一样,属性 行为很少在律师办公室和官方场所之外看到,而且对 民众来说大多是深奥的.为了您的目的,您可以定义一个指向
int
的指针并使其指向数组的开头:int *p = arr;
如果您真的需要一个指向指向int
的指针,您可以将pp
定义为int **pp = &p;
通过
pp
访问数组的第3个元素将写成(*pp)[3]
或pp[0][3]
1.
1 以及其他可读性较差的可能性:*(*pp + 3)
、*(3 + *pp)
和完全晦涩的替代方案:3[*pp]
、3[0[pp]]
。 ..
案例一
这里我们考虑语句:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
以上语句创建了一个名为 arr
的数组,大小为 8
,包含 int
个元素。数组 arr
的类型是 int [8]
.
案例二
这里我们考虑语句:
int **pp = &arr;
以上声明需要注意以下几点:
- 在左侧,我们有一个 指向名为
pp
的int
的指针。也就是说,左边pp
的类型是int**
. - 在右边,我们有表达式
&arr
。由于从案例1,我们知道数组arr
的类型是int [8]
。因此,&arr
是int (*)[8]
,它被读作 指向大小为 8 且元素类型为int
. 的数组的指针
所以基本上,左侧的类型是 int**
(来自第 1 点),而右侧的类型是 int (*)[8]
(来自第 2 点)。也就是说,左边和右边的类型不匹配。这就是编译器给我们错误提示的原因:
error: cannot convert ‘int (*)[8]’ to ‘int**’ in initialization
这意味着您正在尝试初始化 pp
,它是一个 int**
,类型为 int (*)[8]
.[=37 的 initializer =]
要解决这个你需要确保左右手边的类型匹配,如下所示:
int arr[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*pp)[8] = &arr; //now the type on rhs and lhs match
现在左侧 pp
的类型是 int (*)[8]
,它与右侧 &arr
的类型匹配,因此这个程序工作正常。