首页 文章

指向数组/指针数组的C指针消歧

提问于
浏览
430

以下声明之间有什么区别:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

理解更复杂的声明的一般规则是什么?

12 回答

  • -7

    根据经验,右一元运算符(如 []() 等)优先于左运算符 . 所以, int *(*ptr)()[]; 将是一个指向一个函数的指针,该函数返回一个指向int的指针数组(当你离开括号时,尽快得到正确的运算符)

  • 2

    在指向整数的指针中,如果指针递增,则它将转到下一个整数 .

    在指针数组中,如果指针递增,它将跳转到下一个数组

  • 14
    typedef int (*PointerToIntArray)[];
    typedef int *ArrayOfIntPointers[];
    
  • 0

    按照K&R的建议使用cdecl程序 .

    $ cdecl
    Type `help' or `?' for help
    cdecl> explain int* arr1[8];
    declare arr1 as array 8 of pointer to int
    cdecl> explain int (*arr2)[8]
    declare arr2 as pointer to array 8 of int
    cdecl> explain int *(arr3[8])
    declare arr3 as array 8 of pointer to int
    cdecl>
    

    它也是另一种方式 .

    cdecl> declare x as pointer to function(void) returning pointer to float
    float *(*x)(void )
    
  • 406

    我想我们可以使用简单的规则..

    example int * (*ptr)()[];
    start from ptr
    

    ptr 是指向" go towards right ..its "的指针" now go left its a "(" come out go right "()" so "到一个不带参数的函数" go left "并将指针" go right "返回到整数数组" go left "”

  • 250
    int* arr[8]; // An array of int pointers.
    int (*arr)[8]; // A pointer to an array of integers
    

    第三个与第一个相同 .

    一般规则是operator precedence . 随着函数指针的出现,它可以变得更加复杂 .

  • 2

    我不知道它是否有正式名称,但我称之为Right-Left Thingy(TM) .

    从变量开始,然后向右,向左,向右......等等 .

    int* arr1[8];
    

    arr1是一个包含8个整数指针的数组 .

    int (*arr2)[8];
    

    arr2是指向8个整数数组的指针(括号内的左右) .

    int *(arr3[8]);
    

    arr3是一个包含8个整数指针的数组 .

    这应该可以帮助您完成复杂的声明 .

  • 24

    这是我如何解释它:

    int *something[n];
    

    注意优先级:数组下标运算符('[]')的优先级高于解引用运算符('*') .

    所以,这里我们将在'*'之前应用'[]',使语句等效于:

    int *(something[i]);
    

    注意一个声明是如何理解的:int num表示(num)是一个(int),int * ptr或int(* ptr)表示,(ptr处的值)是一个(int),这使得ptr成为指向int的指针 .

    这可以读作,((某物的第i个索引处的值))是一个整数 . 所以,(某事物的第i个索引处的值)是一个(整数指针),这使得某个东西成为整数指针的数组 .

    在第二个,

    int (*something)[n];
    

    要理解这个陈述,你必须熟悉这个事实:

    注意数组的指针表示:somethingElse [i]相当于*(somethingElse i)

    所以,用(* something)替换somethingElse,我们得到*(某事我),这是一个声明的整数 . 所以,( something)给了我们一个数组,它使得某些东西等同于(指向数组的指针) .

  • 5
    int *a[4]; // Array of 4 pointers to int
    
    int (*a)[4]; //a is a pointer to an integer array of size 4
    
    int (*a[8])[5]; //a is an array of pointers to integer array of size 5
    
  • 1

    这是一个有趣的网站,解释了如何在C中读取复杂类型:http://www.unixwiz.net/techtips/reading-cdecl.html

  • 2

    最后两个答案也可以从C中的黄金法则中扣除:

    声明如下使用 .

    int (*arr2)[8];

    如果你取消引用arr2会发生什么?你得到一个8个整数的数组 .

    int *(arr3[8]);

    如果你从arr3中获取一个元素会怎么样?你得到一个指向整数的指针 .

    这在处理指向函数的指针时也很有用 . 以sigjuice为例:

    float *(*x)(void )

    取消引用x后会发生什么?你得到一个你可以不带参数调用的函数 . 你打电话后会发生什么?它将返回指向float的指针 .

    但是,运算符优先级总是很棘手 . 但是,使用括号实际上也可能会造成混淆,因为声明跟随使用 . 至少对我而言,直观地说,arr2看起来像一个由8个指针组成的数组,但它实际上是另一种方式 . 只需要一些习惯 . 足够的理由总是在这些声明中添加注释,如果你问我:)

    edit: example

    顺便说一句,我偶然发现了以下情况:一个具有静态矩阵的函数,它使用指针算法来查看行指针是否超出范围 . 例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))
    
    int *
    put_off(const int newrow[2])
    {
        static int mymatrix[3][2];
        static int (*rowp)[2] = mymatrix;
        int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);
    
        memcpy(rowp, newrow, sizeof(*rowp));
        rowp += 1;
        if (rowp == border) {
            rowp = mymatrix;
        }
    
        return *rowp;
    }
    
    int
    main(int argc, char *argv[])
    {
        int i = 0;
        int row[2] = {0, 1};
        int *rout;
    
        for (i = 0; i < 6; i++) {
            row[0] = i;
            row[1] += i;
            rout = put_off(row);
            printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
        }
    
        return 0;
    }
    

    输出:

    0 (0x804a02c): [0, 0]
    1 (0x804a034): [0, 0]
    2 (0x804a024): [0, 1]
    3 (0x804a02c): [1, 2]
    4 (0x804a034): [2, 4]
    5 (0x804a024): [3, 7]
    

    请注意,border的值永远不会改变,因此编译器可以对其进行优化 . 这与您最初可能要使用的内容不同: const int (*border)[3] :将border声明为指向3个整数数组的指针,只要该变量存在,该数组就不会更改值 . 但是,该指针可以在任何时候指向任何其他这样的数组 . 我们想要参数的那种行为(因为这个函数不会改变任何整数) . 声明如下使用 .

    (p.s . :随意改进这个样本!)

  • 119

    我想第二个声明让许多人感到困惑 . 这是一种理解它的简单方法 .

    让我们有一个整数数组,即 int B[8] .

    让我们也有一个指向B的变量A.现在,A的值是B,即 (*A) == B . 因此A指向整数数组 . 在你的问题中,arr类似于A.

    类似地,在 int* (*C) [8] 中,C是指向整数指针数组的指针 .

相关问题