C语言指针是什么?

什么是指针?

初级理解

简单来说,指针就是存储内存地址的变量。就像普通变量存储数据值一样,指针变量存储的是内存中某个位置的地址。

1
2
int var = 10;    // 普通整型变量
int *ptr = &var; // 指针变量,存储var的地址

在这段代码中:
&var 表示获取变量var的内存地址

int * 声明了一个指向整型的指针变量

ptr 现在存储了var的内存地址

指针的基本操作

  1. 声明指针

指针的声明需要指定它所指向的数据类型:

1
2
3
int *int_ptr;    // 指向整型的指针
float *float_ptr; // 指向浮点数的指针
char *char_ptr; // 指向字符的指针
  1. 取地址操作符(&)

&操作符用于获取变量的内存地址:

1
2
int num = 5;
int *p = # // p现在存储了num的地址
  1. 解引用操作符(*)

*操作符用于访问指针所指向的值:

1
printf("%d", *p); // 输出5,即num的值

指针的用途

指针在C语言中有多种重要用途:

  1. 动态内存分配:通过malloccalloc等函数动态分配内存
  2. 数组操作:数组名本质上就是一个指针
  3. 函数参数传递:通过指针可以实现"按引用传递"
  4. 数据结构实现:链表、树等数据结构都需要使用指针
  5. 字符串处理:C语言中的字符串本质上是字符指针

指针与数组的关系

在C语言中,数组名实际上就是一个指向数组第一个元素的指针:

1
2
3
4
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // 等同于 int *p = &arr[0]

printf("%d", *(p+2)); // 输出3,即arr[2]

多级指针

指针可以指向另一个指针,形成多级指针:

1
2
3
4
5
int var = 10;
int *ptr = &var;
int **pptr = &ptr;

printf("%d", **pptr); // 输出10

指针的常见错误

初学者在使用指针时常犯的错误包括:

  1. 野指针:未初始化的指针
  2. 空指针解引用:对NULL指针进行解引用
  3. 内存泄漏:分配的内存没有释放
  4. 指针越界:访问超出分配的内存范围

指针的高级应用

随着对指针理解的深入,你可以看到更高级的指针应用:

  1. 函数指针:指向函数的指针
  2. 结构体指针:指向结构体的指针
  3. 指针数组:存储指针的数组
  4. 回调函数:通过函数指针实现

指针是C语言的核心概念,虽然初学时可能有些困难,但它是值得投入时间掌握的技能。理解指针不仅能帮助你写出更好的C代码,还能加深你对计算机内存管理的理解。记住:指针就是内存地址,而内存地址就是访问数据的门户。

深入理解

指针变量是存储指针的变量,指针是内存地址这个实际是不严谨的,尽管很多的教材书籍,视频教材等都这么说,只是让初学者更加简单的理解,但是你后面学习计算机组成原理和操作系统后就会明白,指针并不等同于内存地址,而是有一个相应的映射

或者说:

高级语言高级在哪?就是它把底层的东西通过抽象,提供一个简单的接口,人们不用去管它实际是怎么工作的,指针就是如此,它本质是内存地址的抽象,C语言通过指针操作,对内存进行访问控制

指针之面向对象

面向对象是一种编程范式,不是语言功能,很多人说C++和C的区别是C++是面向对象而C是面向过程,这句话是错的,下面演示一下C的面向对象的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdlib.h>
#include <stdio.h>

typedef struct Student Student;
struct Student{
const char* name;
int age;
float score;
const char* (*getName)(Student* student);
int (*getAge)(Student* student);
float (*getScore)(Student* student);
};

static const char* getNameImpl(Student* student) {
return student->name;
}

static int getAgeImpl(Student* student) {
return student->age;
}

static float getScoreImpl(Student* student) {
return student->score;
}

Student* createStudent(const char* name, int age, float score) {
Student* student = (Student*)malloc(sizeof(Student));
student->age = age;
student->score = score;
student->name = name;
student->getAge = getAgeImpl;
student->getName = getNameImpl;
student->getScore = getScoreImpl;
return student;
}

void freeStudent(Student* student) {
free(student);
}

int main()
{
Student* student = createStudent("Alice", 20, 95.5f);
printf("Name: %s\n", student->getName(student));
printf("Age: %d\n", student->getAge(student));
printf("Score: %.2f\n", student->getScore(student));
freeStudent(student);
return 0;
}

名字那里一般不直接拷贝字面量指针,这里只是简单起见这么写

函数实现用static是控制访问性只在本文件内有效,这里简单起见没有拆开到头文件

输出:

1
2
3
Name: Alice
Age: 20
Score: 95.50

显而易见,C中也是可以实现面向对象的


C语言指针是什么?
https://www.blog.jeanhua.cn/2025/04/19/763e18601fde/
作者
jeanhua
发布于
2025年4月19日
许可协议