45

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

例如:

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

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

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

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

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

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

4

10 回答 10

82

采取这种方式:

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

char **p意味着 p 是一个指针,它本身就是一个指向 char 的指针。在此处输入图像描述

于 2011-03-30T10:06:12.933 回答
69
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
于 2011-03-30T09:50:50.000 回答
28

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

char *p意味着您需要*p获取字符,

char **p意味着您需要**p获取字符。

于 2011-03-30T09:48:37.607 回答
19

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

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

x = *p; 

表达式 的类型*pint; 因此,声明p的形式为

int *p;

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

这是 C 和 C++ 语法的一个意外,您可以将该声明编写为int *p;or 或int* p;. 在这两种情况下,它都被解析为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

由于表达式的类型**ppint,因此声明是

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 *),这意味着我们正在传递一个指向 a 的指针FILE *,因此声明为pas FILE **p。请记住,表达式 *pinopenAndInit指的是与表达式 in 相同的f对象main

在声明和表达式中,两者[]()优先级都高于一元*。例如,*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
于 2011-03-30T14:35:58.347 回答
11

我最喜欢的解析复杂声明符的方法是顺时针螺旋规则

基本上,您从标识符开始并遵循顺时针螺旋。请参阅链接以准确了解它的使用方式。

文章没有提到的两件事:

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

2- 如果您遇到表示数组的方括号,请确保您也阅读了以下方括号(如果有的话)。

于 2011-03-30T09:53:47.823 回答
6

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

这里有一些其他的例子

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

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

于 2011-03-30T09:44:25.320 回答
3

你的问题有答案。

实际上,双星用于指示指向指针的指针。

于 2011-03-30T09:44:05.627 回答
2

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

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

char *(*s);这意味着 s 是指向 char 指针的指针,因此 s 不保存 char 的地址,而是保存 char 地址的变量的地址。

于 2011-03-30T09:55:17.117 回答
1

这是一些信息

         variable    pointer
declaring     &a           p

reading/      a            *p

processing
于 2011-03-30T09:55:51.950 回答
-1

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

于 2016-01-14T07:32:48.067 回答