我知道的是,对于以下:指针用C - 1D和2D
int a[10];
a
是该类型int *
a[0]
到的指针,而&a
是int (*)[10]
类型的指针。
现在我的问题是下面的二维数组:
int b[20][30];
是
b
类型int **
的指针?或者它是int (*)[30]
类型的指针?是
&b
int (*)[20][30]
类型的指针?
我知道的是,对于以下:指针用C - 1D和2D
int a[10];
a
是该类型int *
a[0]
到的指针,而&a
是int (*)[10]
类型的指针。
现在我的问题是下面的二维数组:
int b[20][30];
是b
类型int **
的指针?或者它是int (*)[30]
类型的指针?
是&b
int (*)[20][30]
类型的指针?
数组不是指针(这点不能太强调)。
这就是说,一个数组衰减到它的第一个元素的指针。例如:
int a[10];
int b[20][30];
void print_a(int *);
void print_b(int (*)[30]);
print_a(a);
print_b(b);
的a
第一个元素是a[0]
,同样的b
第一元素是b[0]
。你基本上将第一个维度去掉,并将其更改为(*)
;我会稍后解释一下,因为它比这更复杂一点。
指针与数组之间的关系是充满了上下文细微之处并不十分难以把握,但在不同范围的大小信息使得它很有趣,也有助于让你的衰变是如何工作的一个想法:
#include <stdio.h>
int h(int *pa)
{
printf("h(int *): sizeof pa=%zu\n", sizeof pa);
printf("h(int *): sizeof *pa=%zu\n", sizeof *pa);
return *pa;
}
int g(int (*pa)[5])
{
printf("g(int (*)[5]): sizeof pa=%zu\n", sizeof pa);
printf("g(int (*)[5]): sizeof *pa=%zu\n", sizeof *pa);
return h(*pa);
}
int f(int (*pa)[3][5])
{
printf("f(int (*)[3][5]): sizeof pa=%zu\n", sizeof pa);
printf("f(int (*)[3][5]): sizeof *pa=%zu\n", sizeof *pa);
return g(*pa);
}
int main(void)
{
int arr[2][3][5] = {{{11235}}};
printf("main: sizeof arr=%zu\n", sizeof arr);
printf("main: sizeof *arr=%zu\n", sizeof *arr);
printf("%d\n", f(arr));
}
每个指针大小是一样的(这可能并不总是在所有平台上真实的!),而是通过取消引用指针,你看到数组的特定元素的大小,无论你解引用使用一元*
操作或[N]
数组符号,根据定义相当于*((array)+(N))
。
无论如何,回到指针和数组之间的区别,你应该明白,int[20][30]
是不同于int **
。这是为什么?由于int[20][30]
衰变为int(*)[30]
类型的指针,因此在指针解除引用之前不会发生更多衰减。此外,int **
实际上是int *(*)
,这意味着它可以指向指针数组的第一个元素。也就是说,int **
可能曾经是int *[N]
。
int foo[x][y][z] <=> int (*foo)[y][z]
int *foo[m][n] <=> int *(*foo)[n]
int (*foo[a])[b] <=> int (**foo)[b]
在第一种情况下,我们有一个3-D数组,它衰减到一个指向2-D数组的指针;换句话说,除了大小问题之外,数组数组和指向数组的指针在许多情况下是密切相关和可互换的。第一个维度x
是衰减的维度,保留了y
和z
维度。我们有一个二维指针数组。这会衰减为一个指向数组的指针。同样,数组的数组与指向数组的指针密切相关,并且维m
衰变,维数n
。我们有一个指向数组的指针数组。它衰减到一个指向数组的指针。因为尺寸a
最接近变量名称,所以这是衰减的尺寸,保留尺寸b
。需要注意的是,因为它是指向数组的数组,该指针可以指向阵列本身的第一个元素:
int arr[2][3][5];
int (*foo[2])[5] = { arr[0], arr[1] };
int (**foo_ptr)[5] = foo;
回顾:
这个兔子洞显然可以混淆,但我希望我至少帮了一下!
int* temp;
int arraySize = 20;
temp = (int *)malloc(arraySize * sizeof(int));
这会在内存中创建20“整数”长一节,类似于你所提到的。
int** temp;
int arraySize = 20;
int rowSize = 10;
temp = (int **)malloc(arraySize * sizeof(int *));
for(i=0; i<arraySize; i++){
temp[i] = (int *)malloc(rowSize * sizeof(int));
}
这就是2D数组的实际外观。
temp[0]
会给你第一个“数组”的地址。你可以像int *array = temp[0]
这样做,然后像访问正常数组一样访问它,但使用*array[0]
来获得值。
二维数组实际上并不与指针吻合,并且说*temp[0]
获取第一个数组的值。你可以试着去琢磨它,你会发现它,但是现在没有一台可以编译C的机器。
参考,可以帮助:http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html
否,a
是int*
类型的不是,它是int [10]
类型的(即一个阵列型的。)。这就是为什么sizeof(a)
会给你数组的大小(40字节,假设为32位整数)。
同样,b
的类型为int [20][30]
,这是一个数组数组。 I. e。 sizeof(b[0])
是一行数组的大小,在这种情况下是120,整个数组的大小(sizeof(b)
)是行数组的大小的20倍,在这种情况下是2400字节。
诀窍是,在几乎所有上下文中,数组都会衰减为指向其第一个元素的指针。因此,当您在2D阵列上进行指针运算时(如在b[3]
中),b
衰变为类型为int (*)[30]
的指针,因此指针运算跳过行,将行的大小增加三倍(本例中为360字节) - 行是2D数组的元素。结果类型b[3]
是int [30]
,即。即取消引用的指针。
一旦您取消对具有b[3]
的行数组的取消引用,您可以再次调用指针算术来选择此行中的正确元素(b[3][5]
)。再次,数组指针衰减被调用,机制是相同的。
请注意,不存在指针阵列,因为您使用int**
模拟2D阵列时会出现这种情况。由于数组指针衰减,双引号b[3][5]
翻译成类似((int*)b)[3*30 + 5]
的东西,只有元素本身是从内存访问的。
int()[10]'是一个没有或未指定参数的函数类型,它返回一个10个整数的数组。 'a'是一个'int [10]' - 一个10个整数的数组。 –
我不喜欢最后一段;正确的代码将是'((int *)b)[3 * 30 + 5]',这不是“由于衰减” –
@MattMcNabb包含您对更精确代码的建议,谢谢。我昨天写这篇文章的时候很匆忙,昨天对于这种不精确感到抱歉。但是我支持“凭借数组指针衰减”的说法:衰减是使这种转换发生的机制 - 这是使得双重去引用b [3] [5]'表现出如此完全不同的行为的原因取决于'b'是'int [20] [30]'还是'int **'类型。 – cmaster
首先明确指出数组不是指针。指针和数组之间的关系是微妙的。我建议你先阅读tutorial on pointers by Ted Jensen的第二章。
我想简单介绍一下本章所描述的内容。考虑下面的例子。现在
int a[10];
int *p;
你可以写
p=a;
,等效于
p=&a[0];
这件事令许多文本说数组指针的名字。但是,如果你说“这个数组的名字是数组中第一个元素的地址”会更好。
因为虽然你可以写
p=a;
,但你不能写
a=p;
现在来看看你的问题:
从上面的讨论应该清楚,b不是类型为int的指针**。例如:
int b[10][10];
int **x;
int *p;
b=&p; // this is error
x=&p; // this fine
对于其他问题,您可以使用online CDECL。
如果写
int b[10][10];
- >声明B中的INT
int (*p)[10];
阵列10的阵列10 - >声明数p作为指针的阵列10 INT
int (*p)[10][20];
- >声明p为指向数组20的数组10的指针int
否否否。 'a'是一个数组。 'b'是一个数组数组。两者都不是指针。阅读[数组](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c)。 – chris
SO经验法则#2:“我知道X”后面通常会有一个完整的误解。 –
“我知道,对于以下[......]” - 在大多数情况下,是(例如,作为'sizeof'的操作数是一个显着的例外);广告1:它是'int(*)[30]';广告2 .:是的。看看Chris提供的链接。 – mafso