简体   繁体   English

关于如何在C中声明指针的困惑

[英]Confusion about how pointers are declared in C

The syntax commonly used in C to initialize pointers is C中常用于初始化指针的语法是

int *p = &x;

where p is our pointer and x is a previously declared variable. 其中p是我们的指针, x是先前声明的变量。 I unfortunately don't understand this syntax: *p is not equal to &x , but is instead equal to x . 遗憾的是我不理解这种语法: *p 等于&x ,而是等于x So why isn't the correct syntax 那么为什么不是正确的语法

int *p = x;?

Does the compiler simply make an exception to the normal rules of variable assignment when dealing with pointers? 在处理指针时,编译器是否只是对常规变量赋值规则进行了例外处理?

read it this way 这样读

int* p = &x;

ie int* is a type - a pointer to an int; 即int *是一种类型 - 指向int的指针;

The * character has a different meaning depending on where you find it. *字符具有不同的含义,具体取决于您找到它的位置。 I can think of three meaning off the top of my head: 我能想到三个含义:

1. In a declaration 1.在声明中

int *x;

Here, we are writing a variable declaration. 在这里,我们正在编写一个变量声明。 We are creating a variable named x with type int * . 我们正在创建一个名为x的变量,其类型为int *

2. As a dereference in an expression 2.作为表达中的解除引用

int *x = malloc(sizeof(int));
int y = *x;

Here we are using the same token but note that it is now inside an expression! 这里我们使用相同的标记,但请注意它现在在表达式中! (The right hand side of the equal sign is an expression). (等号的右侧是表达式)。 Here it means dereference. 这意味着取消引用。

3. As multiplication 3.作为乘法

int *x = malloc(sizeof(int));
int y = *x * *x;

Here we are using the same character for multiplication! 这里我们使用相同的字符进行乘法运算!

So what gives? 什么给出了什么?

The compiler is able to use the context around the * character to determine which of these three cases we are in. It's certainly arguable that we should have different characters to represent these three things, but that's not the language that we have. 编译器能够使用*字符周围的上下文来确定我们所处的这三种情况中的哪一种。当然可以说我们应该有不同的字符来表示这三种情况,但这不是我们所拥有的语言。

C declaration syntax is admittedly confusing. C声明语法无疑令人困惑。 It generally follows the rule that "declaration follows use", but that's not a hard and fast rule. 通常遵循“声明跟随使用”的规则,但这不是一个硬性规定。

The type name int* means "pointer to int ", but to define an object p of type "pointer to int ", we don't simply write that type name followed by the name of the object: 类型名称int*表示“指向int指针”,但是为了定义类型为“指向int指针”的对象p ,我们不是简单地写入该类型名称,后跟对象的名称:

int* p;

Instead, we write: 相反,我们写道:

int *p;

which means that *p is of type int ; 这意味着*p的类型为int ; it follows from that that p must be of type int* . 由此得出p必须是int*类型。

You've probably noticed that both declarations are the same except for the spacing -- and the compiler doesn't care about spacing. 您可能已经注意到除了间距之外两个声明都是相同的 - 并且编译器不关心间距。 In fact, some programmers prefer to write int* p; 实际上,有些程序员喜欢编写int* p; , even though it doesn't strictly follow the grammar, because it's clearer in this case. ,即使它没有严格遵循语法,因为在这种情况下它更清楚。

The distinction becomes important if you want to define multiple objects in a single declaration: 如果要在单个声明中定义多个对象,则区别变得很重要:

int *p, *q;

means that *p and *q are both of type int . 表示*p*q都是int类型。 And

int *x, y;

means that *x and y are of type int -- which means that x is an int* and y is an int . 表示*xy的类型为int - 这意味着xint*yint Programmers who prefer to place the * next to the int need to split this up into two lines (which is a good idea anyway). 喜欢将*放在int旁边的程序员需要将它分成两行(这无论如何都是个好主意)。

So for an object declaration, the extra specifiers are associated with the name being defined, not with the type. 因此,对于对象声明,额外的说明符与定义的名称相关联,而不是与类型相关联。 But an initializer applies to the newly created object. 但是初始化程序适用于新创建的对象。 So this: 所以这:

int *p;

means that *p is of type int , but this: 表示*p的类型为int ,但是:

int *p = &x;

means that p itself is initialized with the value &x . 意味着p本身用值&x初始化。

I won't try to argue that this is how C's declaration syntax should have been defined. 我不会试图争辩说,这是多么C'S声明语法应该已经确定。 It has its own consistent logic to it, but it's caused a lot of confusion. 它有自己的一致逻辑,但它引起了很多混乱。 But it is the way it is. 但事实就是如此。

Going back to your declaration. 回到你的宣言。

int *p = &x;

Let's take the first half. 我们来看上半场吧。 The "int *p" tells the compiler that the variable 'p' has a location in memory as a value and it should be interpreted as an 'int'. “int * p”告诉编译器变量'p'在内存中的位置是一个值,它应该被解释为'int'。 The second half, '&x', means to get me the location in memory of the variable x. 下半部分'&x',意味着让我获得变量x的内存位置。 So you can save 'location in memory of variable x' into a variable that represents 'location in memory.' 因此,您可以将“变量x的内存中的位置”保存到表示“内存中的位置”的变量中。

A real world analogy would be if you have houses on a street, each with an address (one of the houses would be 'x' in your example), and you also have a postcard, 'p,' on which you can write the address of a house. 一个现实世界的比喻是,如果你在街道上有房子,每个都有一个地址(在你的例子中,其中一个房子将是'x'),你还有一张明信片'p',你可以写一个房子的地址。 You can't put the house, x, on the postcard. 你不能把房子x放在明信片上。 You can only put the address of the house, &x, on the postcard. 您只能将房屋的地址和x放在明信片上。

int *p = &x;

When prefixed with a * in a declaration, an identifier is defined to be a pointer to the given type. 在声明中以*作为前缀时,标识符被定义为指向给定类型的指针。 For example, p is a pointer to x ; 例如, p是指向x的指针; Read it like this: 像这样读:

  • declare a pointer to an int called p 声明一个指向名为pint的指针
  • to the pointer p , assign the following value: the address of x 到指针p ,分配以下值: the address of x

If we want to use p to get the value of x , we do what is called dereferencing: *p 如果我们想使用p来获取x的值,我们会执行所谓的解除引用: *p

For example: 例如:

int x = 35;
int *p = &x;
printf("x = %d\n", *p); // Prints x = 35
printf("%p\n", p); // Prints the address of x (which is the same as the value of p)
printf("%p\n", &p); // Prints the address of the variable p

int x = 5; int x = 5; // Declaring an integer 'x' and initializing it with the value 5. //声明一个整数'x'并用值5初始化它。

int *p1 = &x; int * p1 =&x; // Declaring Pointer 'p1' & Initializing it with address of 'x'. //声明指针'p1'并使用地址'x'初始化它。

printf("x = %d\\n", *p1); printf(“x =%d \\ n”,* p1); // De-referencing Pointer 'p1' to get value of 'x'. //取消引用指针'p1'以获取'x'的值。

int *p2 = NULL; int * p2 = NULL; // Declaraing a Pointer to an int. //声明指向int的指针。 Initialize it to NULL. 将其初始化为NULL。

p2 = &x; p2 =&x; // Assigning address of 'x' to pointer 'p2'. //将'x'的地址分配给指针'p2'。

printf("x = %d\\n", *p2); printf(“x =%d \\ n”,* p2); // De-referencing Pointer 'p2' to get value of 'x'. //取消引用指针'p2'以获取'x'的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM