如何理解C中的指针星*?

Jef*_*rey 35 c pointers dereference

我正在努力使用指针符号*,我发现它在声明和表达式中的使用方式非常混乱.

例如:

int *i; // i is a pointer to an int
Run Code Online (Sandbox Code Playgroud)

但是语法背后的逻辑是什么?*之前的*是什么意思?我们来看下面的例子.请纠正我错在哪里:

char **s;
char *(*s); // added parentheses to highlight precedence
Run Code Online (Sandbox Code Playgroud)

这就是我失去轨道的地方.parantheses之间的*s意味着:s是一个指针?但指针是什么?括号外的*是什么意思:指向s指向的指针?

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

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

pra*_*tri 68

这样吧:

int *i 表示i指向的值是整数.

char **p 表示p是一个指针,它本身就是一个指向char的指针.在此输入图像描述


nos*_*nos 51

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.
Run Code Online (Sandbox Code Playgroud)

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

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

一些例子:

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
Run Code Online (Sandbox Code Playgroud)


小智 22

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

char *p意味着你需要*p得到char,

char **p意味着你需要**p获得char.


Joh*_*ode 12

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

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

x = *p; 
Run Code Online (Sandbox Code Playgroud)

表达式 的类型*pint; 因此,宣言p采取的形式

int *p;
Run Code Online (Sandbox Code Playgroud)

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

这是C和C++语法的意外,您可以将该声明写为int *p;int* p;.在这两种情况下,它被解析为int (*p);- 换句话说,*它始终与变量名称相关联,而不是类型说明符.

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

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

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

int *ap[N];
Run Code Online (Sandbox Code Playgroud)

声明*ap[N]符表示ap是指向数组的位置int.

并且只是为了将点驱动回家,现在假设我们有一个指向指针int并希望访问该值的指针.再一次,我们遵循指针,然后我们取消引用该结果以得到整数值:

x = **pp; // *pp deferences pp, then **pp dereferences the result of *pp
Run Code Online (Sandbox Code Playgroud)

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

int **pp;
Run Code Online (Sandbox Code Playgroud)

声明器**pp指示这pp是指向另一个指针的指针int.

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

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

int main(void)
{
  FILE *f = NULL;
  ...
  openAndInit(&f);
  ...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们希望函数更新值f; 为了做到这一点,我们必须传递指针f.既然f已经是指针类型(FILE *),那意味着我们将指针传递给a FILE *,因此声明为pas FILE **p.请记住,表达 *popenAndInit指的是表达的相同对象fmain做.

在双方的声明和表情,都[]()比一元更高的优先级*.例如,*ap[i]被解释为*(ap[i]); 表达式ap[i]是指针类型,并且*指针取消引用.这ap是一个指针数组.如果要声明指向数组指针,则必须*使用数组名称显式分组,如下所示:

int (*pa)[N]; // pa is a pointer to an N-element array of int
Run Code Online (Sandbox Code Playgroud)

当您想要访问数组中的值时,您必须pa在应用下标之前使用deference :

x = (*pa)[i];
Run Code Online (Sandbox Code Playgroud)

与功能类似:

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
Run Code Online (Sandbox Code Playgroud)


tif*_*tik 9

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

基本上你从标识符开始并遵循顺时针螺旋.请参阅链接以了解其使用方式.

文章没有提到两件事:

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

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


Arm*_*yan 5

int * i表示i是指向int的指针(向后读,读*作为指针). char **p并且char *(*p)两者都表示指向char的指针.

这是其他一些例子

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

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