云计算百科
云计算领域专业知识百科平台

2025 记录C语言指针理解

C语言是我接触编程语言的大门,虽然不难,但是其中指针问题还是困扰许久,后来学了其他编程语言,就把他暂时搁置了。今天,重新对指针内容进行了更加深入的了解,下面,就来聊聊这神秘的指针。大佬过目完记得给出建议哦!

一、我理解的指针

指针,又称指针变量,本质上是一种变量,用来存放地址,允许程序直接访问内存地址。像其他诸如 int 类型的变量存放的是整型数据,只有整型数据才能赋值给 int 变量,同样的道理,只有地址数据才能赋值给指针

无论什么类型是数据,都需要在内存中开辟空间来存放,那必然会有对应的内存地址。在C语言中可以通过取地址符 & 来获得每个变量的地址,这些地址就可以赋值给指针变量。同个地址指向的数据都是相同的,只要改变地址中数据的值,那么其他地方使用到该数据的值都会一起改变!

二、指针的声明

在C语言中,如果我们要声明一个整型变量,那么我们会有如下声明语句:

int a;

还有其他声明变量的语句,诸如:

float b;
char c;

不难看出,声明一个变量都是由 数据类型+变量名 开始的,那么,指针变量的声明是否是同样的方式呢?

先说结论,指针变量是声明也是同样的道理,请看:

// 声明一个指向整型(int)的指针,初始值为 NULL(空指针)
int* a = NULL;

// 声明一个指向字符型(char)的指针,用于操作字符串或单个字符
char* b = NULL;

// 声明一个指向浮点型(float)的指针,可用于动态分配浮点数组
float* c = NULL;

// 声明一个指向双精度浮点型(double)的指针
double* ptr_double = NULL;

初始化指针为 NULL 是良好的编程习惯,可以避免野指针问题

ps:其实指针的声明还有其他写法,虽然形式不同,但是都是一样的作用,这里我只写我觉得有助于理解的一种,其他形式可以查阅资料。

这里,int* 、char* 、float* 、double* 是指针变量的类型,a、b、c是变量名,这样一看是不是很清楚了。

跟整型变量一样,整型变量只能存放整型数据,不能存放字符型、浮点型等其他变量。指针虽然说只能存放地址数据,但是也是有要求的,如 int* 型指针,它只能存放整型变量的地址,不能将字符型等其他类型数据的地址赋值给 int*。正所谓各回各家,这是在一开始声明就已经决定好的,不然为什么要那么麻烦,定义那么多种声明指针的类型呢,直接用一个就可以了呀。

这个地方,每个人的理解不一样,有些大佬会把指针的声明分成3部分,但是我感觉只要能理解就都一样,所以,这里记录的是我自己的理解,如果对你有帮助那非常荣幸,如果觉得与你理解有冲突那也没关系,每个人的理解都不同。我们都是站在巨人的肩膀上学习的,如果没能帮助到你,还有其他非常优秀的大佬,我也是参考了很多大佬的文章,才有了这篇理解的,一起加油呀!

三、指针的使用

1、指针赋值

指针是用来存放地址数据的,所以,我们可以将每个变量的地址赋值给指针,如下:

int a = 10; // 定义普通整型变量
int* p; // 定义一个指向整型的指针
p = &a; // 将变量a的地址赋给指针p

可以通过取地址符 “ & ” 将变量的地址取出,通过赋值操作,将地址数据赋值给指针。

2、解引用指针

前面提到,指针存放的是变量的地址,那么,我们能否通过指针,取到其存放的对应数据呢?

这就不得不提到 解引用指针 了,解指针便是将指针中地址指向的数据取出来。利用 “ * ” 便可做到。

格式:

*指针名

示例:

#include <stdio.h>

int main() {
int a = 10;
int* p; // 1. 定义指针
p = &a; // 2. 指针指向变量a的地址

// 解引用指针:访问p所指向的值
printf("a的值是: %d\\n", a); // 输出: 10
printf("p指向的值是: %d\\n", *p); // 输出: 10(*p 就是 a)

// 修改p指向的值
*p = 20; // 相当于 a = 20;

printf("修改后a的值是: %d\\n", a); // 输出: 20

return 0;
}

可以看出,解指针得到的 *p 等同于其执行的变量 a,对 *p 操作就是对 a 操作。

3、特殊的指针——数组名

数组名其实是特殊的指针,为常量,其指向数组的第一个元素,通过数组名解指针得到的是第一个元素的值,如:

#include <stdio.h>

int main() {
int arr[5] = {10, 20, 30, 40, 50};

// 使用数组名访问第一个元素
printf("First element: %d\\n", arr[0]); // 10
printf("Third element: %d\\n", *arr); // 10,等价于 arr[0]

// 使用指针算术访问第三个元素
printf("Third element: %d\\n", *(arr + 2)); // 30,等价于 arr[2]

// 遍历数组并打印所有元素
for (int i = 0; i < 5; ++i) {
printf("Element %d: %d\\n", i, *(arr + i));
}

return 0;
}

回想我们定义数组时,是不是还要指定数组的类型呢,整型数组不能存放浮点型的数据,这便跟前面提到的指针一样。在数组中,由于存放时同种类型的数据,每个数据需要的内存空间已经固定,所以可以通过第一个元素的地址,加上一单位,找到下一个元素。

比如:在int型数组中,每个元素占4字节,那么程序会自动计算,在该数组中,一个单位就是4字节,就能立即找到下一个元素,回想我们在使用数组的时候,是不是通过a[0] 、a[1] 、a[2] 的方式来获取数组中对应位置的元素呢。a[0]就是第0个元素,也是首地址+0单位;a[1]是第一个元素,也是首地址+1单位;…….

4、函数实参应用

当我们在函数中使用指针作为实参时,其传递的其实是变量的地址,如果通过指针改变数据的值,那么也会改变原本变量的值。

形式一:调用函数时,如果传递的是普通变量的变量名,那么程序只会把该变量的值复制一份用于实参传递,当在函数中改变实参的值,并不会改变主函数中变量的值;

#include <stdio.h>

// 函数:尝试修改传入的整数
void modifyByValue(int x) {
x = 100; // 修改的是副本
printf("函数内 x = %d\\n", x);
}

int main() {
int a = 10;
printf("调用前 a = %d\\n", a);

modifyByValue(a); // 传入普通变量(值传递)

printf("调用后 a = %d\\n", a); // a 的值未改变

return 0;
}

输出结果

调用前 a = 10
函数内 x = 100
调用后 a = 10

形式二:调用函数时,如果传递的是普通变量的地址——指向该变量的指针,那么实际传递的实参为改地址值,在函数中通过该实参改变的值,是会直接改变主函数中变量的值。

#include <stdio.h>

// 函数:通过指针修改变量
void modifyByPointer(int *p) {
*p = 200; // 修改 p 指向的内存中的值
printf("函数内 *p = %d\\n", *p);
}

int main() {
int b = 20;
printf("调用前 b = %d\\n", b);

modifyByPointer(&b); // 传入变量的地址(指针做实参)

printf("调用后 b = %d\\n", b); // b 的值被修改

return 0;
}

输出结果

调用前 b = 20
函数内 *p = 200
调用后 b = 200

指针的知识还有很多,我所理解的不过是其中一点,想更深入理解还需要再查看其他资料。很高兴能帮助到你,如果有写错,欢迎指正!

记录于2025.07.30

赞(0)
未经允许不得转载:网硕互联帮助中心 » 2025 记录C语言指针理解
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!