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

发布于 2024-10-29 05:10:37 字数 447 浏览 1 评论 0原文

我正在与指针符号 * 作斗争,我发现它在声明和表达式中的使用方式非常令人困惑。

例如:

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

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

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

这就是我失去踪迹的地方。括号之间的 *s 的意思是:s 是一个指针?但指向什么的指针呢?括号外的 * 是什么意思:指向 s 所指向的指针?

那么这句话的意思就是:指向s所指向的指针是指向char的指针吗?

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

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:

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?

So the meaning of this is: The pointer pointing to what s is pointing is a pointer to a 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

﹉夏雨初晴づ 2024-11-05 05:10:37

可以这样理解:

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

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

Take it this way:

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

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

林空鹿饮溪 2024-11-05 05:10:37
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
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
浅沫记忆 2024-11-05 05:10:37

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

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

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

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

char *p means you need *p to get the char,

char **p means you need **p to get the char.

岛徒 2024-11-05 05:10:37

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

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

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 dereference the pointer, like so:

x = *p; 

The type of the expression *p is int; therefore, the declaration of p takes the form

int *p;

In this declaration, int is the type specifier, and *p is 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 p is a pointer type. The declaration can be read as either "p is of type pointer to int" or "p is a pointer to type int". I prefer to use the second form, others prefer the first.

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.

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:

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 ap is

int *ap[N];

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

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

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

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

int **pp;

The declarator **pp indicates that pp is a pointer to another pointer to an 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 f is already a pointer type (FILE *), that means we are passing a pointer to a FILE *, hence the declaration of p as FILE **p. Remember that the expression *p in openAndInit refers to the same object that the expression f in main does.

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 ap is 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:

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 pa before applying the subscript:

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
ζ澈沫 2024-11-05 05:10:37

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

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

本文没有提到两件事:

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

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

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.

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

只想待在家 2024-11-05 05:10:37

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

下面是一些其他示例

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

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

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

Here's some other examples

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

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

澉约 2024-11-05 05:10:37

你的问题中已有答案。

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

You have the answer in your questions.

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

盛夏已如深秋| 2024-11-05 05:10:37

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

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

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

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 *b means b can hold the address of some int, the type of the reference is important, since in pointers arithmetic, pointer + 1 is actually pointer + (1 * sizeof(*pointer)).

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

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.

西瑶 2024-11-05 05:10:37

这是一些信息

         variable    pointer
declaring     &a           p

reading/      a            *p

processing

here is a bit of information

         variable    pointer
declaring     &a           p

reading/      a            *p

processing
爱给你人给你 2024-11-05 05:10:37

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文