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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5484624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:13:22  来源:igfitidea点击:

How to understand the pointer star * in C?

cpointersdereference

提问by Jeffrey

I'm struggling with the pointer sign *, I find it very confusing in how it's used in both declarations and expressions.

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

For example:

例如:

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

But what is the logic behind the syntax? What does the * just before the i mean? Let's take the following example. Please correct me where I'm wrong:

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

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

And this is where I lose track. The *s between the parantheses means: s is a pointer? But a pointer to what? And what does the * outside the parentheses mean: a pointer to what s is pointing?

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

So the meaning of this is: The pointer pointing to what s is pointing is a pointer to a char?

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

I'm at a loss. Is the * sign interpreted differently in declarations and expressions? If so, how is it interpreted differently? Where am I going wrong?

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

采纳答案by burningice

The rule of declaration in c is, you declare it the way you use it.

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

char *pmeans you need *pto get the char,

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

char **pmeans you need **pto get the char.

char **p意味着你需要**p得到字符。

回答by pradeepchhetri

Take it this way:

这样做:

int *imeans the value to which i points is an integer.

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

char **pmeans that p is a pointer which is itself a pointer to a char.enter image description here

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

回答by nos

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.

Is the * sign interpreted differently in declarations and expressions?

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

Yes. They're completely different. in a declaration * is used to declare pointers. In an expression unary * is used to dereference a pointer (or as the binary multiplication operator)

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

Some examples:

一些例子:

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

回答by John Bode

Declarations in C are expression-centric, meaning that the form of the declaration should match the form of the expression in executable code.

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

For example, suppose we have a pointer to an integer named p. We want to access the integer value pointed to by p, so we dereferencethe pointer, like so:

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

x = *p; 

The type of the expression*pis int; therefore, the declaration of ptakes the form

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

int *p;

In this declaration, intis the type specifier, and *pis the declarator. The declarator introduces the name of the object being declared (p), along with additional type information not provided by the type specifier. In this case, the additional type information is that pis a pointer type. The declaration can be read as either "pis of type pointer to int" or "pis a pointer to type int". I prefer to use the second form, others prefer the first.

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

It's an accident of C and C++ syntax that you can write that declaration as either int *p;or int* p;. In both cases, it's parsed as int (*p);-- in other words, the *is always associated with the variable name, not the type specifier.

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

Now suppose we have an array of pointers to int, and we want to access the value pointed to by the i'th element of the array. We subscript into the array and dereference the result, like so:

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

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

Again, the type of the expression*ap[i]is int, so the declaration of apis

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

int *ap[N];

where the declarator *ap[N]signifies that apis an array of pointers to int.

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

And just to drive the point home, now suppose we have a pointer to a pointer to intand want to access that value. Again, we deference the pointer, then we dereference that result to get at the integer value:

只是为了把这个点带回家,现在假设我们有一个指向int并想要访问该值的指针的指针。同样,我们引用指针,然后我们取消引用该结果以获得整数值:

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

Since the type of the expression **ppis int, the declaration is

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

int **pp;

The declarator **ppindicates that ppis a pointer to another pointer to an int.

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

Double indirection shows up a lot, typically when you want to modify a pointer value you're passing to a function, such as:

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

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

int main(void)
{
  FILE *f = NULL;
  ...
  openAndInit(&f);
  ...
}

In this case, we want the function to update the value of f; in order to do that, we must pass a pointer to f. Since fis already a pointer type (FILE *), that means we are passing a pointer to a FILE *, hence the declaration of pas FILE **p. Remember that the expression*pin openAndInitrefers to the same object that the expression fin maindoes.

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

In both declarations and expressions, both []and ()have higher precedence than unary *. For example, *ap[i]is interpreted as *(ap[i]); the expression ap[i]is a pointer type, and the *dereferences that pointer. Thus apis an array of pointers. If you want to declare a pointer to an array, you must explicitly group the *with the array name, like so:

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

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

and when you want to access a value in the array, you must deference pabefore applying the subscript:

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

x = (*pa)[i];

Similarly with functions:

与函数类似:

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

回答by tiftik

My favorite method to parse complicated declarators is the clockwise-spiral rule.

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

Basically you start from the identifier and follow a clockwise spiral. See the link to learn exactly how it's used.

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

Two things the article doesn't mention:

文章没有提到的两件事:

1- You should separate the type specifier (int, char, etc.) from the declarator, parse the declarator and then add the type specifier.

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

2- If you encounter square brackets which denote an array, make sure you read the following square brackets (if there are any) as well.

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

回答by Armen Tsirunyan

int * imeans i is a pointer to int (read backwards, read * as pointer). char **pand char *(*p)both mean a pointer to a pointer to char.

int * i表示 i 是一个指向 int 的指针(向后读,读 * 作为指针)。 char **p并且char *(*p)都表示指向char的指针的指针。

Here's some other examples

这是其他一些例子

int* a[3]// a is an array of 3 pointers to int

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

int (*a)[3]//a is a pointer to an array of 3 ints

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

回答by Shamim Hafiz

You have the answer in your questions.

你有你的问题的答案。

Indeed a double star is used to indicate pointer to pointer.

事实上,双星用于表示指针到指针。

回答by MByD

The * in declaration means that the variable is a pointer to some other variable / constant. meaning it can hold the address of variable of the type. for example: char *c;means that c can hold the address to some char, while int *bmeans b can hold the address of some int, the type of the reference is important, since in pointers arithmetic, pointer + 1is actually pointer + (1 * sizeof(*pointer)).

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

The * in expression means "the value stored in the address" so if cis a pointer to some char, then *cis the specific char.

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

char *(*s);meaning that s is a pointer to a pointer to char, so s doesn't hold the address of a char, but the address of variable that hold the address of a char.

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

回答by Akshatha

here is a bit of information

这是一些信息

         variable    pointer
declaring     &a           p

reading/      a            *p

processing

回答by ShoveItUpYour____

Declaring &ameans it points to *i. After all it is a pointer to *int. An integer is to point *i. But if consider j = *kis the pointer to the pointer this, means &kwill be the value of kand kwill have pointer to *int.

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