一个本质:
指针的本质是内存地址的别名,它指向一个变量或对象在内存中的位置。在编程语言中,指针通常是一个变量,它存储了另一个变量或对象的内存地址。通过指针,我们可以间接地访问和修改该变量或对象的值。
简单地说,指针是地址公开化了。内存地址是本来就存在的,并不是因为有了指针,才出现了地址概念,所有的进程都会有地址,java写的代码有地址,Python写的代码也会有地址。但只有c/c++把这个概念明确出来,这也是c/c++开发的便利性,也是它的复杂性。
指针的作用在于,它可以让我们在内存中移动数据,以及在不同的内存地址之间传递数据。指针也可以用于动态内存分配和释放,以及函数参数传递等方面。
两种计算
指针的取值和取地址是两个不同的操作。
- *p:指针的取值操作是将指针所指向的内存地址中的值取出来,赋值给指针变量本身。例如,如果有一个指针变量p指向一个整型变量x的内存地址,那么执行语句p = &x;后,p的值就变成了x的内存地址。
- &a: 指针的取地址操作是将指针变量本身的内存地址取出来。例如,如果有一个指针变量p指向一个整型变量x的内存地址,那么执行语句&p;就会返回p的内存地址。
- 需要注意的是,指针的取值和取地址操作的操作数和结果类型是不同的。指针的取值操作的操作数是指针变量,结果类型是指针变量所指向的数据类型;而指针的取地址操作的操作数是指针变量本身,结果类型是指针变量的类型。
三个便利
-
在数组中,每个元素都有一个唯一的内存地址,可以通过该地址访问该元素的值。而通过数组名或数组指针,我们可以获取数组中任意一个元素的内存地址,从而访问该元素的值。因此,数组名和数组指针都可以看作是一种特殊的指针,它们指向数组中的第一个元素的内存地址。
在数组/结构体中,每个元素都有一个唯一的内存地址,可以通过该地址访问该元素的值。而通过数组名或数组指针,我们可以获取数组中任意一个元素的内存地址,从而访问该元素的值。因此,数组名和
数组指针都可以看作是一种特殊的指针
,它们指向数组中的第一个元素的内存地址。结构体指针也可以看作是一种特殊的指针
,它指向结构体中的第一个元素的内存地址。int arr[5] = {1, 2, 3, 4, 5}; int *p = &arr[0]; // 定义指针p并将其指向数组arr的第一个元素 *p = 6; // 将指针p所指向的元素的值修改为6 p++; // 将指针p指向数组arr的下一个元素 *p = 7; // 将指针p所指向的元素的值修改为7
-
在C/C++等编程语言中,函数可以接收指针作为参数,也可以返回指针作为结果。通过指针作为参数,函数可以接收任意类型的数据,并可以在函数内部修改该数据。通过指针作为结果,函数可以返回任意类型的数据,并可以在函数外部使用该数据。
- 指针函数
#include <stdio.h> void print(int *p) { printf("The value of the pointer is: %d\\n", *p); } int main() { int x = 10; int *p = &x; print(p); return 0; }
- 函数指针
#include <stdio.h> void print(int x) { printf("The value of x is: %d\\n", x); } void (*pf)(int) = print; int main() { int x = 10; pf(x); return 0; }
-
动态内存分配是在程序运行时为变量或对象分配内存空间的一种方式。在C/C++等编程语言中,动态内存分配通常使用malloc、new等函数来实现。这些函数会在堆上为变量或对象分配内存空间,并返回一个指向该内存空间的指针。
指针可以用于动态内存分配和释放。通过指针,我们可以在堆上分配内存空间,并将指针指向该内存空间的起始地址。然后,我们可以使用指针来访问和修改该内存空间中的数据。当不再需要该内存空间时,我们可以使用指针来释放该内存空间。