【问题标题】:How to understand the pointer star * in C?如何理解C中的指针星*?
【发布时间】:2011-07-25 23:19:50
【问题描述】:

我正在为指针符号 * 苦苦挣扎,我发现它在声明和表达式中的使用方式非常令人困惑。

例如:

int *i; // i is a pointer to an int

但是语法背后的逻辑是什么? i 前面的 * 是什么意思?让我们看下面的例子。请纠正我的错误:

char **s;
char *(*s); // added parentheses to highlight precedence

这就是我迷路的地方。括号之间的 *s 表示:s 是指针?但是指向什么的指针?括号外的 * 是什么意思:指向 s 的指针?

所以这里的意思是:指向s所指向的指针是指向一个char的指针吗?

我很茫然。 * 符号在声明和表达式中的解释是否不同?如果是这样,它如何解释不同?我哪里错了?

【问题讨论】:

    标签: c pointers dereference


    【解决方案1】:

    声明&a 表示它指向*i。毕竟它是一个指向*int 的指针。一个整数指向*i。但如果考虑j = *k 是指向指针this 的指针,则意味着&k 将是k 的值,而k 将具有指向*int 的指针。

    【讨论】:

      【解决方案2】:

      c 中的声明规则是,你以你使用它的方式声明它。

      char *p 表示您需要*p 来获取字符,

      char **p 表示您需要**p 才能获取字符。

      【讨论】:

        【解决方案3】:

        C 中的声明以表达式为中心,这意味着声明的形式应与可执行代码中的表达式形式相匹配。

        例如,假设我们有一个指向名为p 的整数的指针。我们要访问p指向的整数值,所以我们取消引用指针,如下所示:

        x = *p; 
        

        表达式的类型*pint;因此,p 的声明采用以下形式

        int *p;
        

        在此声明中,int类型说明符*p声明符。声明器引入了被声明对象的名称 (p),以及类型说明符未提供的其他类型信息。在这种情况下,附加的类型信息是p是一个指针类型。声明可以读作“p 是指向int 的类型指针”或“p 是指向int 类型的指针”。我更喜欢使用第二种形式,其他人更喜欢第一种。

        您可以将声明编写为int *p;int* p;,这是C 和C++ 语法的一个意外。在这两种情况下,它都被解析为int (*p);——换句话说,* 总是与变量名相关联,而不是类型说明符。

        现在假设我们有一个指向int 的指针数组,我们想要访问数组中第 i 个元素所指向的值。我们对数组进行下标并取消引用结果,如下所示:

        x = *ap[i]; // parsed as *(ap[i]), since subscript has higher precedence
                    // than dereference.
        

        同样,表达式*ap[i]的类型是int,所以ap的声明是

        int *ap[N];
        

        其中声明符*ap[N] 表示ap 是指向int 的指针数组。

        为了说明问题,现在假设我们有一个指向int 的指针,并且想要访问该值。同样,我们尊重指针,然后我们取消引用该结果以获得整数值:

        x = **pp; // *pp deferences pp, then **pp dereferences the result of *pp
        

        由于表达式**pp的类型是int,所以声明是

        int **pp;
        

        声明符**pp 表示pp 是指向另一个指向int 的指针。

        双重间接出现很多,通常是当您想要修改传递给函数的指针值时,例如:

        void openAndInit(FILE **p)
        {
          *p = fopen("AFile.txt", "r");
          // do other stuff
        }
        
        int main(void)
        {
          FILE *f = NULL;
          ...
          openAndInit(&f);
          ...
        }
        

        在这种情况下,我们希望函数更新f 的值;为此,我们必须传递一个指向f 的指针。由于f 已经是指针类型(FILE *),这意味着我们将指针传递给FILE *,因此p 的声明为FILE **p。请记住,openAndInit 中的 表达式 *pmain 中的表达式 f 所指的对象相同。

        在声明和表达式中,[]() 的优先级都高于一元 *。例如*ap[i]被解释为*(ap[i]);表达式ap[i] 是一个指针类型,* 取消引用该指针。因此ap 是一个指针数组。如果你想声明一个指向数组的指针,你必须明确地将* 与数组名分组,如下所示:

        int (*pa)[N]; // pa is a pointer to an N-element array of int
        

        当你想访问数组中的一个值时,你必须在应用下标之前遵从pa

        x = (*pa)[i];
        

        功能类似:

        int *f(); // f is a function that returns a pointer to int
        ...
        x = *f(); // we must dereference the result of f() to get the int value
        
        int (*f)(); // f is a pointer to a function that returns an int
        ...
        x = (*f)(); // we must dereference f and execute the result to get the int value
        

        【讨论】:

          【解决方案4】:
          int i; //i is an int.
          int *i; //i is a pointer to an int
          int **i;//i is a pointer to a pointer to an int.
          

          *号在声明和表达式中的解释不同吗?

          是的。他们完全不同。在声明中 * 用于声明指针。在表达式中,一元 * 用于取消引用指针(或作为二元乘法运算符)

          一些例子:

          int i = 10; //i is an int, it has allocated storage to store an int.
          int *k; // k is an uninitialized pointer to an int. 
                  //It does not store an int, but a pointer to one.
          k = &i; // make k point to i. We take the address of i and store it in k
          int j = *k; //here we dereference the k pointer to get at the int value it points
                      //to. As it points to i, *k will get the value 10 and store it in j
          

          【讨论】:

            【解决方案5】:

            这样说:

            int *i表示i指向的值是一个整数。

            char **p 表示 p 是一个指针,它本身就是一个指向 char 的指针。

            【讨论】:

              【解决方案6】:

              这里有一些信息

                       variable    pointer
              declaring     &a           p
              
              reading/      a            *p
              
              processing
              

              【讨论】:

                【解决方案7】:

                声明中的 * 表示该变量是指向其他变量/常量的指针。意味着它可以保存该类型变量的地址。例如:char *c;表示c可以保存某个char的地址,而int *b表示b可以保存某个int的地址,引用的类型很重要,因为在指针算术中,pointer + 1实际上是@ 987654324@.

                表达式中的 * 表示“存储在地址中的值”,因此如果 c 是指向某个字符的指针,则 *c 是特定字符。

                char *(*s);表示s是一个指向char的指针,所以s不保存char的地址,而是保存char地址的变量的地址。

                【讨论】:

                  【解决方案8】:

                  我最喜欢的解析复杂声明符的方法是clockwise-spiral rule

                  基本上,您从标识符开始并遵循顺时针螺旋。请参阅链接以了解其具体使用方法。

                  文章没有提到的两件事:

                  1- 应该将类型说明符(int、char 等)与声明符分开,解析声明符,然后添加类型说明符。

                  2- 如果遇到表示数组的方括号,请务必阅读以下方括号(如果有的话)。

                  【讨论】:

                  • 你能给你的1和2举个例子吗?有读数?会很好的补充
                  • 请注意,如果您想“顺时针”调用该规则,您还必须记住从名称向上走,否则您会得到不正确的结果。
                  【解决方案9】:

                  int * i 表示 i 是指向 int 的指针(向后读取,将 * 读取为指针)。 char **pchar *(*p) 都表示指向 char 指针的指针。

                  这里有一些其他的例子

                  int* a[3] // a 是一个包含 3 个指向 int 的指针的数组

                  int (*a)[3] //a 是一个指向 3 个整数数组的指针

                  【讨论】:

                    【解决方案10】:

                    你的问题有答案。

                    确实用双星来表示指向指针的指针。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-10-08
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多