C-1D和2D中的指针
我知道,由于以下原因:C-1D和2D中的指针,c,pointers,C,Pointers,我知道,由于以下原因: int a[10]; a是指向a[0]的int*类型的指针,而&a是int(*)[10]类型的指针 现在我的问题是关于以下2D阵列: int b[20][30]; b是int**类型的指针吗?或者它是int(*)[30]类型的指针 &b是int(*)[20][30]类型的指针吗 这将在内存中创建一个20“int”长的部分,与您提到的类似 int** temp; int arraySize = 20; int rowSize = 10; temp = (int **)m
int a[10];
a
是指向a[0]
的int*
类型的指针,而&a
是int(*)[10]
类型的指针
现在我的问题是关于以下2D阵列:
int b[20][30];
b
是int**
类型的指针吗?或者它是int(*)[30]
类型的指针&b
是int(*)[20][30]
类型的指针吗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));
}
int**temp;
int-arraySize=20;
int rowSize=10;
temp=(int**)malloc(arraySize*sizeof(int*);
对于(i=0;i否,a
不是int*
类型,它是int[10]
类型(即数组类型)。这就是为什么sizeof(a)
会给出数组的大小(40字节,假设32位整数)
同样地,b
属于int[20][30]
类型,它只是一个数组数组。例如,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 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
int a[10];
int b[20][30];
void print_a(int *);
void print_b(int (*)[30]);
print_a(a);
print_b(b);
对于您的其他问题,您可以使用
如果你写信
intb[10][10];
-->将b声明为int的数组10的数组10
int(*p)[10];
-->将p声明为指向int的数组10的指针
int(*p)[10][20];
-->将p声明为指向int的数组20的数组10的指针数组不是指针(这一点怎么强调都不过分)
也就是说,数组衰减为指向其第一个元素的指针。例如:
int b[10][10];
int **x;
int *p;
b=&p; // this is error
x=&p; // this fine
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]
。你基本上把第一个维度去掉,改成a(*)
;我稍后会解释得更多,因为它有点复杂
指针和数组之间的关系充满了上下文的微妙之处,并不难理解,但不同范围内的大小信息让它变得有趣,也有助于让您了解衰减是如何工作的:
#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));
}
在第一种情况下,我们有一个3-D数组,它衰减为指向2-D数组的指针;换句话说,数组数组和指向数组的指针除了大小问题外,在许多情况下是密切相关和可互换的。第一个维度x
是衰减的维度,留下y
和z
维度。
在第二种情况下,我们有一个二维指针数组。这会衰减为指向指针数组的指针。同样,数组数组与指向数组的指针密切相关,维度m
衰减,留下维度n
在第三种情况下,我们有一个指向数组的指针数组。它衰减为指向数组指针的指针。由于维度a
与变量名最接近,这就是衰减的变量名,留下维度b
。请注意,由于它是指向数组的指针数组,指针可以指向数组t的第一个元素hemselves:
int arr[2][3][5];
int (*foo[2])[5] = { arr[0], arr[1] };
int (**foo_ptr)[5] = foo;
概述:
- 数组(大小A)的数组(大小B)指向数组(大小B)的指针
- 指针到指针的指针数组(大小A)
- 衰减/增长的数组始终是最内层的数组/指针,最内层的数组/指针与变量声明中的变量名最接近,数组的关联性高于指针,当然括号会起到很大的作用
这个兔子洞显然会让人困惑,但我希望我至少帮了一点忙!不不不不。a
是一个数组。b
是一个数组数组。两者都不是指针。请阅读。所以经验法则2:“我知道X”后面通常会有一个完全的误解。“我知道,这是为了下面的[…]”-在大多数情况下,是(例如,作为操作数到sizeof
是一个明显的例外);ad 1:它是int(*)[30]
;ad 2:是。请查看Chris提供的链接。a