C 指针取消引用运算符-语法规则
我不确定star运算符的正确用法。请考虑以下例子:C 指针取消引用运算符-语法规则,c,pointers,C,Pointers,我不确定star运算符的正确用法。请考虑以下例子: #include<stdio.h> int main() { char *w[3]; //Array of pointers w[0] = "Apple"; w[1] = "Pear"; w[2] = "Peach"; printf("w[0] = %s, w[1] = %s, w[2] = %s\n", w[0], w[1], w[2]); char **p = &a
#include<stdio.h>
int main() {
char *w[3]; //Array of pointers
w[0] = "Apple";
w[1] = "Pear";
w[2] = "Peach";
printf("w[0] = %s, w[1] = %s, w[2] = %s\n", w[0], w[1], w[2]);
char **p = &w[0];
char ***q = &p;
printf("&w[0] = %p, *p = %s, p = %p, q = %p, *q = %p, **q = %s\n",
&w[0], *p, p, q, *q, **q);
return 0;
}
上面,p
是指向指针的指针p
保存&w[0]
的地址,*p
返回&w[0]
中的值。是否应该使用**p=“Apple
?
同样,不应该是***q=“Apple
,而应该是**q
我没能找到一个资源来让我非常清楚地知道指向Npointers操作符的指针的正确用法。从这个意义上讲,任何建议都将受到高度赞赏。我希望我能够充分表达我的问题。printf(“%s”,p)
希望p
是char*
类型。如果p
为If typechar**
则需要取消对其的引用以获得char*
简单示例:
p w[0]
------- ------- --------------------
| | | | |
| 0x05 | | 0x00 | | 'A' p' 'p' 'l' 'e'
------- ------- --------------------
&p 0x07 &w[0] 0x06 0x00 ------------
*p将给您0x00
**p会给你“A”
上面,p是指向指针的指针。p持有&w[0]的地址
您认为p
是指向指针的指针,这是正确的
您认为p
包含&w[0]
的地址是错误的。正确的说法是“p
持有w[0]
的地址”
&
被解读为“的地址”,这就是赋值的原因char**p=&w[0]代码>法律。认为
w[0]
是一个char*
这意味着&w[0]
是与p
类型兼容的char**
因此p
被分配了w[0]
的地址。这与说“p
指向w[0]
”相同。因此*p
是一个引用w[0]
。*p
和w[0]
都有类型char*
,并指向内存中相同的字符串“Apple”
请注意,文本字符串的类型是char[]
,因为C中的字符串是作为字符数组实现的。这将强制透明地char*
进行初始化w
(感谢@David Bowling的更正)现在我将尝试对指针进行一些澄清,为了便于理解,我现在将以简化的方式公开内容
C中的指针和其他任何类型的指针一样,都是一个变量,其类型是内存中的地址
不幸的是,仅仅有一个指向进程内存中某个地方的地址不足以在没有损坏指针所指向位置附近的其他实体(通常是变量)的风险的情况下正确地进行交互。因此,该语言提供了指针的限定条件,允许用户指定它指向的对象(类型),并允许编译器根据指向的对象选择访问内存的方式
说到这里,回到最初的问题,现在应该很清楚,指针是一个变量,可以保存C语言中存在的任何类型的地址,基本的或派生的
现在我们进入正式部分。为了与指针交互,我们需要一些运算符来处理它们,基本上是一个解析为变量地址的运算符,一个解析为指针中变量的值的运算符,以及一个声明运算符“declare”指针
让我们从解引用操作符*
开始。此运算符从指向对象的指针返回对象的值(取消引用)。但它也是指针的声明符,因为它是指针最自然的视觉表示。请看以下声明:
int * p_int;
char *w[3];
char **p = &w[0];
char ***q = &p;
char **p = &w[0];
按照C风格,从右到左阅读声明,我们可以说:
p_int
是一个被引用的变量,它给出了int
的值
它是一个指针
现在,如果我们在解除引用时将变量p_int
声明为指向int
类型对象的指针,编译器知道要返回int
值,它必须从指针指向的位置开始访问内存字节,并打包若干字节,在我们使用的机器/编译器上请求int
,一起形成int
无论如何,指针和任何其他变量一样,必须初始化或分配以包含有效地址,然后才能用于某些事情。因此,我们必须初始化/为指针分配一个值,该值必须与指针指向的对象类型兼容。如果我们有一个变量:
int an_int;
如果是兼容类型,则可能适合范围。但指针保留对象的地址,因此我们无法直接分配:
p_int = an_int; //The compiler will trigger an error for incompatible type
要分配它,我们必须获得变量内存中的地址。我们需要一元运算符&
,它返回应用它的对象的地址
p_int = &an_int; //we assign to p_int the address in memory of an_int
当然,我们可以通过解引用再次访问存储在指针指向的地址处的值:
int another_int = *p_int;
在结束之前,我们必须讨论C语言为数组保留的一种“特殊处理”。在C中,数组的名称会自动转换为其第一个元素的地址(下面我们将看到标准中对此存在哪些限制)。这意味着数组声明后面的两行是等效的:
int array_of_int[10];
int *p_int = array_of_int;
int *p_int1 = &array_of_int[0];
(甚至int*p_int1=&array\u of_int;
都是等效的,原因我们将在下面看到)。
现在我们考虑你的例子。宣言:
int * p_int;
char *w[3];
char **p = &w[0];
char ***q = &p;
char **p = &w[0];
必须读作“w
是指向char的三个指针数组,p
是指向int
指针的指针,q
是指向int
指针的指针”
让我们解码。数组的每个元素<代码