C多维数组中的指针地址
我在搞多维数组和指针。我一直在看一个程序,它打印出一个简单数组的内容和地址。以下是我的数组声明:C多维数组中的指针地址,c,arrays,memory,pointers,multidimensional-array,C,Arrays,Memory,Pointers,Multidimensional Array,我在搞多维数组和指针。我一直在看一个程序,它打印出一个简单数组的内容和地址。以下是我的数组声明: int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} }; 我目前的理解是zippo是一个指针,它可以保存其他几个指针的地址。默认情况下,zippo保存指针zippo[0]的地址,它还可以保存指针zippo[1]、zippo[2]和zippo[3]的地址 现在,以下面的陈述为例: p
int zippo[4][2] = { {2,4},
{6,8},
{1,3},
{5,7} };
我目前的理解是zippo
是一个指针,它可以保存其他几个指针的地址。默认情况下,zippo
保存指针zippo[0]
的地址,它还可以保存指针zippo[1]
、zippo[2]
和zippo[3]
的地址
现在,以下面的陈述为例:
printf("zippo[0] = %p\n", zippo[0]);
printf(" *zippo = %p\n", *zippo);
printf(" zippo = %p\n", zippo);
在我的机器上,它提供以下输出:
zippo[0] = 0x7fff170e2230
*zippo = 0x7fff170e2230
zippo = 0x7fff170e2230
我完全理解为什么
zippo[0]
和*zippo
具有相同的值。它们都是指针,并且都存储整数2的地址(默认情况下),或者zippo[0][0]
。但是zippo
也共享相同的内存地址是怎么回事?zippo
是否应该存储指针的地址zippo[0]
?什么?这里重要的是int-zippy[4][2]
与int**zippo
的对象类型不同
就像intzippi[5]
,zippy
是内存块的地址。但是编译器知道,您希望使用二维语法寻址从zippy
开始的八个内存位置,但希望使用一维语法寻址从zippi
开始的五个内存位置
zippo
完全是另一回事。它保存一个内存块的地址,该内存块大到足以包含两个指针,如果让它们指向某些整数数组,则可以使用二维数组访问语法取消对它们的引用。zippo
不是指针。这是一个数组值数组<0..4中的i
的code>zippo和zippo[i]
在某些情况下(特别是在值上下文中)会“衰减”到指针。请尝试打印zippo的大小,以了解在非值上下文中使用zippo的示例。在这种情况下,sizeof
将报告数组的大小,而不是指针的大小
在值上下文中,数组的名称衰减为指向其第一个元素的指针。因此,在值上下文中,zippo
与&zippo[0]
相同,因此具有类型“指向int
的数组[2]的指针”*zippo
,在值上下文中与&zippo[0][0]
相同,即“指向int
”的指针。它们的值相同,但类型不同
我推荐阅读来回答你的第二个问题。指针具有相同的“值”,但指向不同的空间量。请尝试打印zippo+1
和*zippo+1
,以便更清楚地看到:
#include <stdio.h>
int main(void)
{
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} };
printf("%lu\n", (unsigned long) (sizeof zippo));
printf("%p\n", (void *)(zippo+1));
printf("%p\n", (void *)(*zippo+1));
return 0;
}
告诉我机器上的sizeof(int)
是4,第二个和第三个指针的值不相等(如预期的那样)
另外,“%p”
格式说明符需要*printf()
函数中的void*
,因此您应该在printf()
调用中将指针强制转换为void*
(printf()
是一个可变函数,因此编译器无法在此处为您执行自动转换)
编辑:当我说数组“衰减”为指针时,我的意思是值上下文中数组的名称等效于指针。因此,如果我有tpt[100]
对于某些类型T
,则名称pt
在值上下文中为T*
类型。对于sizeof
和一元&
运算符,名称pt
不会减少为指针。但是你可以做T*p=pt代码>-这是完全有效的,因为在此上下文中,pt
属于T*
类型
请注意,这种“衰减”只发生一次。那么,假设我们有:
int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} };
然后,值上下文中的zippo
衰减为类型为的指针:指向int
数组[2]的指针。代码:
int (*p1)[2] = zippo;
是有效的,而
int **p2 = zippo;
将触发“指针分配不兼容”警告
使用上文定义的zippo
int (*p0)[4][2] = &zippo;
int (*p1)[2] = zippo;
int *p2 = zippo[0];
都是有效的。使用printf(“%p\n”((void*)名称)打印时,它们应打印相同的值代码>,但指针的不同之处在于它们分别指向整个矩阵、一行和一个整数。当您声明多维数组时,编译器将其视为一维数组。多维数组只是使我们的生活更轻松的一种抽象。您有一个误解:这不是一个指向4个数组的数组,它总是一个连续的内存块
在您的情况下,请执行以下操作:
int zippo[4][2]
真的和做什么一样吗
int zippo[8]
使用编译器为您处理的2D寻址所需的数学
详细信息,请参见C++中的< /P>
这与执行以下操作非常不同:
int** zippo
或
在本例中,您正在创建一个包含四个指针的数组,这些指针可以分配给其他数组。当数组表达式出现在大多数上下文中时,其类型将从“T的N元素数组”隐式转换为“指向T的指针”,其值设置为指向数组中的第一个元素。此规则的例外情况是当数组表达式是sizeof
或(&
)运算符地址的操作数时,或者当数组是用作声明中初始值设定项的字符串文字时
因此,表达式zippo
“衰减”从类型int[4][2]
(int的2元素数组的4元素数组)到int(*)[2]
(指向int的2元素数组的指针)。类似地,zippo[0]
的类型是int[2]
,它被隐式转换为int*
给定声明intzippo[4][2]
,下表显示了涉及zippo和任何隐式
int** zippo
int* zippo[4]
Expression Type Implicitly converted to Equivalent expression
---------- ---- ----------------------- ---------------------
zippo int [4][2] int (*)[2]
&zippo int (*)[4][2]
*zippo int [2] int * zippo[0]
zippo[i] int [2] int *
&zippo[i] int (*)[2]
*zippo[i] int zippo[i][0]
zippo[i][j] int
&zippo[i][j] int *
*zippo[i][j] invalid