2014-07-16 77 views
2

我知道的是,对于以下:指针用C - 1D和2D

int a[10]; 

a是该类型int *a[0]到的指针,而&aint (*)[10]类型的指针。

现在我的问题是下面的二维数组:

int b[20][30]; 
  1. b类型int **的指针?或者它是int (*)[30]类型的指针?

  2. &bint (*)[20][30]类型的指针?

+3

否否否。 'a'是一个数组。 'b'是一个数组数组。两者都不是指针。阅读[数组](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c)。 – chris

+3

SO经验法则#2:“我知道X”后面通常会有一个完整的误解。 –

+0

“我知道,对于以下[......]” - 在大多数情况下,是(例如,作为'sizeof'的操作数是一个显着的例外);广告1:它是'int(*)[30]';广告2 .:是的。看看Chris提供的链接。 – mafso

回答

3

数组不是指针(这点不能太强调)。

这就是说,一个数组衰减到它的第一个元素的指针。例如:

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是衰减的维度,保留了yz维度。我们有一个二维指针数组。这会衰减为一个指向数组的指针。同样,数组的数组与指向数组的指针密切相关,并且维m衰变,维数n。我们有一个指向数组的指针数组。它衰减到一个指向数组的指针。因为尺寸a最接近变量名称,所以这是衰减的尺寸,保留尺寸b。需要注意的是,因为它是指向数组的数组,该指针可以指向阵列本身的第一个元素:

int arr[2][3][5]; 
int (*foo[2])[5] = { arr[0], arr[1] }; 
int (**foo_ptr)[5] = foo; 

回顾:

  • 阵列的阵列(尺寸A)(尺寸B)指针< =>指向阵列(尺寸B)
  • 阵列(尺寸A)< =>指针的指针
  • 该衰减/生长总是最里面的阵列/指针的阵列,所述最内层是所述一个最接近变量中的变量名称e声明,数组具有比指针更高的关联性,尽管括号使得所有的区别变得明显。

这个兔子洞显然可以混淆,但我希望我至少帮了一下!

0
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

1

否,aint*类型的不是,它是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]的东西,只有元素本身是从内存访问的。

+0

int()[10]'是一个没有或未指定参数的函数类型,它返回一个10个整数的数组。 'a'是一个'int [10]' - 一个10个整数的数组。 –

+0

我不喜欢最后一段;正确的代码将是'((int *)b)[3 * 30 + 5]',这不是“由于衰减” –

+0

@MattMcNabb包含您对更精确代码的建议,谢谢。我昨天写这篇文章的时候很匆忙,昨天对于这种不精确感到抱歉。但是我支持“凭借数组指针衰减”的说法:衰减是使这种转换发生的机制 - 这是使得双重去引用b [3] [5]'表现出如此完全不同的行为的原因取决于'b'是'int [20] [30]'还是'int **'类型。 – cmaster

3

首先明确指出数组不是指针。指针和数组之间的关系是微妙的。我建议你先阅读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