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]
    类型的指针吗

  • 这将在内存中创建一个20“int”长的部分,与您提到的类似

    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