我正在努力使用指针符号*,我发现它在声明和表达式中的使用方式非常混乱。
例如:
int *i; // i is a pointer to an int
但语法背后的逻辑是什么? *之前的*是什么意思?我们来看下面的例子。请纠正我错在哪里:
char **s;
char *(*s); // added parentheses to highlight precedence
这就是我失去轨道的地方。 parantheses之间的* s意味着:s是一个指针?但指针是什么?括号外的*是什么意思:指向s指向的指针?
所以这个意思是:指向s指向的指针是指向char的指针?
我很茫然。 *符号在声明和表达式中的解释是否不同?如果是这样,它的解释方式有何不同?我哪里错了?
答案 0 :(得分:65)
这样做:
int *i
表示i指向的值是整数。
char **p
表示p是一个指针,它本身就是一个指向char的指针。
答案 1 :(得分:49)
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
答案 2 :(得分:22)
c中的声明规则是,你以你使用它的方式声明它。
char *p
表示您需要*p
来获取字符
char **p
表示您需要**p
来获取字符。
答案 3 :(得分:10)
C中的声明是以表达式为中心的,这意味着声明的形式应该与可执行代码中表达式的形式相匹配。
例如,假设我们有一个指向名为p
的整数的指针。我们想要访问p
指向的整数值,所以我们取消引用指针,如下所示:
x = *p;
表达式的类型 *p
为int
;因此,p
的声明采用
int *p;
在此声明中,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.
同样,表达式 *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
。请记住,*p
中的表达式 openAndInit
引用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
答案 4 :(得分:9)
我最喜欢的解析复杂声明符的方法是clockwise-spiral rule。
基本上,你从标识符开始,顺时针旋转。请参阅链接以了解其使用方式。
文章没有提到两件事:
1-您应该将类型说明符(int,char等)与声明符分开,解析声明符,然后添加类型说明符。
2-如果遇到表示数组的方括号,请务必阅读以下方括号(如果有的话)。
答案 5 :(得分:5)
int * i
表示我是指向int的指针(向后读,读*作为指针)。
char **p
和char *(*p)
都表示指向char的指针。
以下是其他一些例子
int* a[3]
// a是一个由3个指向int
int (*a)[3]
// a是指向3个整数的数组的指针
答案 6 :(得分:2)
你的问题有答案。
实际上,双星用于指示指针的指针。
答案 7 :(得分:1)
声明中的*表示变量是指向其他变量/常量的指针。意思是它可以保存类型变量的地址。例如:char *c;
表示c可以将地址保存到某个char,而int *b
表示b可以保存某些int的地址,引用的类型很重要,因为在指针算术中pointer + 1
1}}实际上是pointer + (1 * sizeof(*pointer))
。
表达式中的*表示“存储在地址中的值”,因此如果c
是指向某个字符的指针,则*c
是特定字符。
char *(*s);
意味着s是指向char的指针,因此s不保存char的地址,而是保存char的地址的变量的地址。
答案 8 :(得分:0)
这里有一些信息
variable pointer
declaring &a p
reading/ a *p
processing
答案 9 :(得分:0)
声明&a
表示它指向*i
。毕竟它是指向*int
的指针。整数是指向*i
。但是如果考虑j = *k
是指向this的指针,则意味着&k
将是k
的值,而k
将指向*int
。