我是C++的初学者(并且不了解C,来自Java和Python背景)。
我正在学习指针,并运行了我从我的自我教程文件中共享的以下代码:
#include<iostream>
using namespace std;
int main() {
//What is a pointer:-
// A datatype that holds address of a variable in other datatype
int a=3;
int* b = &a; //CREATE A POINTER THAT POINTS TO A
// '&'STANDS FOR ADDRESS OF OPERATOR
// '*' IS CALLED DEREFERNCING OPERATOR
cout<< b<<endl; //prints address of a
cout<<&a<<endl; //does the same stuff
//retrieving stored at a particular address
// '*' GIVES VALUE AT THE ADDRESS STORED IN POINTER
cout<<*b<<endl;
cout<<*&a<<endl;
//pointer to a pointer
int** c = &b; // pointer to another pointer b
cout<<"The address of b is"<<c<<endl;
cout<<"The address of b is"<<&b<<endl;
cout<<"The value at address c is"<<*c<<endl;
cout<<"The value at address value stored in c is "<< **c<<endl;
return 0;
}
这给我返回了以下输出:-
0x94ac7ff7d4
0x94ac7ff7d4
3
3
The address of b is 0x94ac7ff7c8
The address of b is 0x94ac7ff7c8
The value at address c is 0x94ac7ff7d4
The value at address value stored in c is 3
引起好奇心的是输出的最后四行 我们看到:-c
指向b
和b
指向a
它们本身不是变量,那么为什么它们不返回相同的地址呢? 这是否意味着对同一变量使用多个指针会占用系统资源,从而导致设计不佳?
一张图片胜过千言万语。
+----------------+
a: | 3 | 94ac7ff7d4
+----------------+
^
|
`-------------.
|
+--------------|-+
b: | 0x94ac7ff7d4 * | 94ac7ff7d8
+----------------+
^
|
`-------------.
|
+--------------|-+
c: | 0x94ac7ff7d8 * | 94ac7ff7dc
+----------------+
我认为变量a
是一个可以容纳整数的小盒子。 在C语言中,我们通过标识符a
来知道它,但实际上,在机器级别,编译器已将其分配给地址0x94ac7ff7d4
。
同样,b
是一个小框,可以容纳指向整数的指针,该指针通常实现为存储整数的地址(数字)。 我们通过标识符b
知道它,但实际上,编译器已将其分配给地址0x94ac7ff7d8
。
最后,c
是一个框,可以保存指向整数的指针,该指针再次实现为存储指针的地址。 我们通过标识符c
知道它,虽然你没有这么说,但我猜编译器已经将其分配给地址0x94ac7ff7dc
.
对于任何变量,&
都会为您提供存储变量的地址 - 这是您可以存储在指针变量中的值类型。
对于指针值,*
为您提供指针指向的值。 (对于指向指针的指针,**
为您提供指针指向、指向的指针等的值。
请记住,C是一种非常低级的语言。许多东西实际上没有花哨的处理就存在。
int *b;
b 是一个变量,就像任何值一样。它存在于地址0x94ac7ff7c8
处,包含值0x94ac7ff7d4
;
int **c = &b;
c
它存在于内存中(在程序未计算的地址处),它与值0x94ac7ff7c8
相同,与b
的地址相同。
与 php 的引用不同,C 的指针不会自动指向"real"变量。 执行此操作时,您所做的只是为c
赋值,因为这就是=
运算符所做的。
c = 0x94ac7ff7c8;
因此,C 和 B 包含不同的值。
当评估"**c
"时,您会问:
"地址c的价值是多少?0x94ac7ff7c8
.好的,那么地址0x94ac7ff7c8
持有的值是多少?"这个问题的答案是**c
请注意,以下行具有两种不同的含义:
int **c = x;
**c = x;
首先,您声明的是双指针类型。星号属于表达式int **
。此处 x 必须是类型int **
在第二个中,您将取消引用c
两次。星号属于表达式**c
如*(*(c))
。此处 x 必须是类型int
这种区别不会造成歧义,因为在声明指针时不可能取消引用指针。它没有值,因此没有要获取的地址。
如果你只写&a
那么它就不是一个变量,但是一旦你声明了一个整数,它就变成了名为b
的变量,恰好存储另一个变量的地址。
声明为指针的变量是指针类型的对象。他们占据了自己的记忆。
所以这些声明
int a=3;
int* b = &a;
int** c = &b;
声明三个存储不同值的不同变量。第一个变量的类型为int
并将值存储3
。第二个变量的类型为int *
并存储第一个变量的地址。第三个变量的类型为int **
并存储第二个变量的地址。
如果您有这样的声明
T a;
其中 T 是某种类型说明符,则指向此变量的指针声明将如下所示
T *p = &a;
例如,其中 T 可以int *
.在这种情况下,您将获得声明
int * *p = &a;
或省略多余的空白,如下所示
int **p = &a;
指针与其他对象一样是一个对象。它有一个类型和一个值。通常,指针保存另一个对象的地址,尽管这并不像您想象的那样特别。
考虑一下:
int a = 0;
int b = 0;
int* p = &a;
p = &b;
int* p = &a;
初始化p
以指向a
。p
s 的值是a
的地址。下一行指出p
指向b
。现在p
的值是b
的地址。指针值需要存储在某个地方,就像int a = 0;
值0
需要存储在某个地方一样。
在内存中,int a
和int* p
的值只是位和字节。只有解释为"整数"或"指向整数"才能使指针变得特别。
为什么指针与它们指向的变量没有相同的地址?
指针是与指针指向的对象不同的对象(除非指针指向自身)。具有重叠存储持续时间的两个不同对象通常不能存储在同一地址中。
它们本身不是变量
这是一个不正确的假设。b
和c
本身就是变量。
这是否意味着对同一变量使用多个指针会占用系统资源
大多数对象可能会消耗内存。指针对象也不例外。
从而导致设计不佳?
没有办法从前提下得出这样的结论。有时许多指针是有益的。
根据"非变量"的印象考虑以下代码。
int a = 3;
int b = 4;
int *p = &a;
std::cout << p << " -> " *p << std::endl;
p = &b;
std::cout << p << " -> " *p << std::endl;
列表项
变量是计算机主内存 (RAM) 中的内存位置,用于存储数据。 指针是计算机主内存 (RAM) 中的内存位置,用于存储变量的地址。 指针与它们所指向的变量的地址不同,因为指针也是一种变量,它具有不同的和自己的地址。