Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C多维数组中的指针地址_C_Arrays_Memory_Pointers_Multidimensional Array - Fatal编程技术网

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