这些指针的含义,指针指针,函数指针和数组指针

Posted

技术标签:

【中文标题】这些指针的含义,指针指针,函数指针和数组指针【英文标题】:meaning of these pointers, pointer-to-pointer, function pointer and array pointer 【发布时间】:2020-06-08 15:36:34 【问题描述】:

我是一名大学生,我们的老师让我们说出这些指针的含义,但我只能弄清楚其中的一些:

1. int *p1;
2. int *p2[10];
3. int (*p3)[10];
4. int (*p4)();
5. int **p5();
6. int (**p6)[10];
7. int (**p7)();
8. int *(*p8)();
9. int (*p9[10])();
10. int **p10[10];

这是我到目前为止所想出的:

p1 是一个指向 int 的指针 p2 是一个包含 10 个 int 指针的数组 p3 是指向具有 10 个元素的静态数组的指针 p4 是一个函数指针 p5 根本不是指针,而是返回 int** 的函数原型 p6 是一个包含 10 个指针的数组 p7 是指向函数指针的指针

你们能帮帮我吗?因为我们的老师告诉我们这些将在考试中进行

【问题讨论】:

如果你想具体一点,例如在 p4 中:p4 是一个指向函数的指针,不带参数并返回 int。那么p8应该更容易。唯一的区别是返回值。 这是你的作业吗? 不是真正的作业,我老师说有的要考试 【参考方案1】:

cdecl.org 可用于破译您的示例中的杂乱声明:

int (*p9[10])(); => 将 p9 声明为数组 10,指向返回 int 的函数的指针

如果做不到这一点,您可以使用Clockwise/Spiral Rule 手动打磨它们。

【讨论】:

【参考方案2】:

所有7个指针都正确确定,但你应该指定参数类型和返回类型。

例如:

    int **p5(); - 不带参数的函数,返回指向 int 的指针。

    int *(*p8)(); - 指向不带参数的函数的指针,返回指向 int 的指针。 int (*p9[10])(); - 包含 10 个指针的数组,指向不带参数的函数,返回 intint **p10[10]; - 包含 10 个指针的数组,指向指向 int 的指针。

如果我是编译器,我可以提示空参数列表,例如 f.e.铿锵声:

"警告:此函数声明不是原型 [-Wstrict-prototypes]"

在实践中使用这些构造时,请使用 (void) 而不是 ()


请注意,如果您正在参加考试,请想想 David Anderson 的 Clockwise/Spiral Rule,如图所示 here。

【讨论】:

【参考方案3】:

1>指向整数的指针

int *p1;
```````````````````````````````````````
2>array of 10 pointer which point to integer
`````````````````````````````````
int *p2[10];
`````````````````````````````````
3> pointer to an array of 10 integers
```````````````````````
int (*p3)[10]
``````````````````````````````````````
4> pointer to function that takes void argument and return integer
`````````````
int (*p4)();
```````````````
5>> is a prototype(deceleration)  of a function which called p5 and returns int** 
````````````
int **p5();
``````````
6>> is an array of 10 pointer-to-pointer which point to integer values
`````````
 int (**p6)[10]
````````
7>>is pointer to pointer to function that takes void argument and return int
``````````````
int (**p7)();
````````````````
8>>pointer to function that takes void argument and return address or pointer
`````````````````
int *(*p8)();
`````````````
9>>array of 10 pointers to functions that take void argument and return an integer
``````````````````
 int (*p9[10])();
```````````````
10>> it indicate to the first element in an array of 10 pointers which point to integer values 
```````````
int **p10[10];
```````````

【讨论】:

【参考方案4】:

有一些技巧可以阅读和理解复杂的声明。有一个称为“顺时针螺旋规则”的技巧,您从标识符开始,然后从右边的任何内容开始向外螺旋。例如,给定声明

int *(*a[N])(void);

我们将其追踪为:

                 +-----------------------+
                 | +-----------+         |
                 | | +-------+ |         |
                 | | | +-+   | |         |
                 | | | | |   | |         |
             int * ( * a [N] ) ( void )  |
             ^   | | |   |   | |         |
             |   | | +---+   | |         |
             |   | +---------+ |         |
             |   +-------------+         |
             +---------------------------+

                   a                -- a
                   a[N]             -- is an N-element array
                  *a[N]             -- of pointers
                 (*a[N])(    )      -- to functions taking
                 (*a[N])(void)      --   no parameters
                *(*a[N])(void)      -- returning pointer to
            int *(*a[N])(void);     -- int

请记住,后缀下标[] 和函数调用() 运算符的优先级高于一元解引用运算符*,因此*a[i]*f() 等表达式被解析为*(a[i])*(f()) - 我们取消引用 a[i]f() 的结果。如果a指向一个数组,那么我们需要索引到*aresult,所以我们需要使用括号将*a-(*a)[i]显式分组。同样,如果f指向一个函数,那么我们需要调用*f的结果,所以我们要写(*f)()

这是一个多重间接的例子:

int **foo(void);

分解为

      foo             -- foo
      foo(    )       -- is a function taking
      foo(void)       --   no parameters
     *foo(void)       -- returning a pointer
    **foo(void)       -- to a pointer
int **foo(void);      -- to int

您可以递归地将这些规则应用于任何函数参数。下面是标准库中signal 函数的声明:

void (*signal(int sig, void (*func)(int)))(int);

读作

       signal                                    -- signal
       signal(                          )        -- is a function taking
       signal(    sig                   )        --   parameter sig
       signal(int sig                   )        --     is an int
       signal(int sig,        func      )        --   parameter func
       signal(int sig,       *func      )        --     is a pointer
       signal(int sig,      (*func)(   ))        --     to a function taking
       signal(int sig,      (*func)(int))        --       parameter unnamed is an int
       signal(int sig, void (*func)(int))        --     returning void
     (*signal(int sig, void (*func)(int)))       -- returning a pointer
     (*signal(int sig, void (*func)(int)))(   )  -- to a function taking
     (*signal(int sig, void (*func)(int)))(int)  --   unnamed parameter is an int
void (*signal(int sig, void (*func)(int)))(int); -- returning void

您还可以使用一些替换技巧。如果你需要弄清楚如何声明一个指向函数的指针数组,返回指向其他函数的指针,返回指向指向int的指针数组的指针,从T的数组开始:

T a[N];   // a is an array of T

这将是一个指向某事物的指针数组,因此请将 T 替换为指针类型 P

P *a[N];  // a is an array of pointer to P

每个a[i] 都将是一个指向函数的指针,因此请将P 替换为函数类型F

F (*a[N])( );

这些函数中的每一个都返回一个指针,因此请将F 替换为另一种指针类型P

P *(*a[N])( );

这些指针中的每一个都指向另一个函数,所以

F (*(*a[N])( ))( );

那些函数返回指针,所以我们将F替换为另一种指针类型P

P *(*(*a[N])( ))( );

P替换为数组类型A

A (*(*(*a[N])( ))( ))[M];

从这里我们可以直接跳到最后:

int *(*(*(*a[N])( ))( ))[M];

【讨论】:

以上是关于这些指针的含义,指针指针,函数指针和数组指针的主要内容,如果未能解决你的问题,请参考以下文章

02指针进阶

指针数组与数组指针

函数指针数组举例

C++ 指针与数组

指针,数组指针,指针数组,函数指针解析

指针,数组指针,指针数组,函数指针解析