如何理解C中的指针星*?
我正在与指针符号 * 作斗争,我发现它在声明和表达式中的使用方式非常令人困惑。
例如:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
可以这样理解:
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.是的。他们完全不同。在声明中 * 用于声明指针。在表达式中,一元 * 用于取消引用指针(或作为二进制乘法运算符)
一些示例:
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:
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.C 中的声明是以表达式为中心的,这意味着声明的形式应与可执行代码中的表达式的形式相匹配。
例如,假设我们有一个指向名为
p
的整数的指针。我们想要访问p
指向的整数值,因此我们取消引用该指针,如下所示:表达式的类型
*p
是int
;因此,p
的声明采用以下形式:在此声明中,
int
是类型说明符,*p
是声明符。声明符引入了所声明的对象的名称 (p
),以及类型说明符未提供的其他类型信息。在这种情况下,附加类型信息是p
是指针类型。该声明可以解读为“p
是指向int
类型的指针”或“p
是指向int< 类型的指针” /代码>”。我更喜欢使用第二种形式,其他人更喜欢第一种。
您可以将该声明编写为
int *p;
或int* p;
,这是 C 和 C++ 语法的一个意外。在这两种情况下,它都被解析为int (*p);
——换句话说,*
始终与变量名相关联,而不是与类型说明符相关联。现在假设我们有一个指向 int 的指针数组,并且我们想要访问该数组的第 i 个元素所指向的值。我们为数组添加下标并取消引用结果,如下所示:
同样,表达式
*ap[i]
的类型是int
,因此ap
的声明是声明符
*ap[N]
表示ap
是指向int
的指针数组>。为了让大家明白这一点,现在假设我们有一个指向
int
的指针,并且想要访问该值。再次,我们引用指针,然后取消引用该结果以获取整数值:由于表达式
**pp
的类型为int
,因此声明为声明符
**pp
表示pp
是一个指向另一个指向int
的指针的指针。双重间接寻址经常出现,通常是当您想要修改传递给函数的指针值时,例如:
在本例中,我们希望函数更新
f
的值;为此,我们必须传递一个指向f
的指针。由于f
已经是指针类型 (FILE *
),这意味着我们正在传递一个指向FILE *
的指针,因此声明 <代码>p 为FILE **p
。请记住,openAndInit
中的表达式*p
与main 中的表达式
f
引用同一个对象。是的。在声明和表达式中,
[]
和()
的优先级都高于一元*
。例如,*ap[i]
被解释为*(ap[i])
;表达式 ap[i] 是指针类型,并且* 取消引用该指针。因此,
ap
是一个指针数组。如果要声明指向数组的指针,则必须将*
与数组名称显式分组,如下所示:当您想要访问数组中的值时,在应用下标之前必须遵循
pa
:与函数类似:
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 byp
, so we dereference the pointer, like so:The type of the expression
*p
isint
; therefore, the declaration ofp
takes the formIn 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 thatp
is a pointer type. The declaration can be read as either "p
is of type pointer toint
" or "p
is a pointer to typeint
". 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;
orint* p;
. In both cases, it's parsed asint (*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:Again, the type of the expression
*ap[i]
isint
, so the declaration ofap
iswhere the declarator
*ap[N]
signifies thatap
is an array of pointers toint
.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:Since the type of the expression
**pp
isint
, the declaration isThe declarator
**pp
indicates thatpp
is a pointer to another pointer to anint
.Double indirection shows up a lot, typically when you want to modify a pointer value you're passing to a function, such as:
In this case, we want the function to update the value of
f
; in order to do that, we must pass a pointer tof
. Sincef
is already a pointer type (FILE *
), that means we are passing a pointer to aFILE *
, hence the declaration ofp
asFILE **p
. Remember that the expression*p
inopenAndInit
refers to the same object that the expressionf
inmain
does.In both declarations and expressions, both
[]
and()
have higher precedence than unary*
. For example,*ap[i]
is interpreted as*(ap[i])
; the expressionap[i]
is a pointer type, and the*
dereferences that pointer. Thusap
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:and when you want to access a value in the array, you must deference
pa
before applying the subscript:Similarly with functions:
我最喜欢的解析复杂声明符的方法是顺时针螺旋规则。
基本上,您从标识符开始并遵循顺时针螺旋。请参阅链接以了解其具体使用方法。
本文没有提到两件事:
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.
int * i
表示 i 是一个指向 int 的指针(向后读取,将 * 读取为指针)。char **p
和char *(*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
andchar *(*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 intint (*a)[3]
//a is a pointer to an array of 3 ints你的问题中已有答案。
实际上,双星用于指示指针到指针。
You have the answer in your questions.
Indeed a double star is used to indicate pointer to pointer.
声明中的 * 意味着该变量是指向其他变量/常量的指针。这意味着它可以保存该类型变量的地址。例如:
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, whileint *b
means b can hold the address of some int, the type of the reference is important, since in pointers arithmetic,pointer + 1
is actuallypointer + (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.这是一些信息
here is a bit of information
声明
&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 considerj = *k
is the pointer to the pointer this, means&k
will be the value ofk
andk
will have pointer to*int
.