C语言指针知识总结
一、指针的本质与基础概念
指针是C语言的灵魂,它是专门存储内存地址的变量类型。理解指针是掌握C语言的关键。
核心概念:
定义格式:指向的空间类型 *变量名;
int num = 100; // 普通整型变量
int *p = # // p是指向整型变量的指针
-
p存储num的内存地址
-
*p可直接操作num的值(解引用)
指针大小与系统关系:
32位系统 | 4字节 | sizeof(int*) == 4 |
64位系统 | 8字节 | sizeof(void*) == 8 |
野指针与空指针:
// 危险!野指针(指向随机地址)
int *wild_ptr;
*wild_ptr = 100; // 可能导致程序崩溃
// 安全做法:初始化为NULL
int *safe_ptr = NULL;
if (safe_ptr != NULL) {
*safe_ptr = 200; // 安全访问
}
经典案例:
#include <stdio.h>
int main() {
int score = 95;
int *p_score = &score;
printf("变量地址: %p\\n", &score); // 0x7ffd42a
printf("指针存储的地址: %p\\n", p_score); // 同上
printf("通过指针访问值: %d\\n", *p_score); // 95
*p_score = 100; // 修改原变量值
printf("修改后的分数: %d\\n", score); // 100
return 0;
}
二、多级指针深度解析
二级指针是指向指针的指针,常用于动态内存管理和函数参数传递。
内存模型:
text
二级指针 一级指针 变量
+——-+ +——-+ +——-+
pp —> | 地址 | -> | 地址 | -> | 值 |
+——-+ +——-+ +——-+
实用案例:
#include <stdio.h>
int main() {
int classroom = 301;
int *p_room = &classroom; // 一级指针
int **pp_room = &p_room; // 二级指针
printf("教室号: %d\\n", classroom); // 301
printf("通过一级指针访问: %d\\n", *p_room); // 301
printf("通过二级指针访问: %d\\n", **pp_room); // 301
// 修改原始值
**pp_room = 501;
printf("修改后的教室号: %d\\n", classroom); // 501
return 0;
}
指针偏移特性:
int arr[3] = {10, 20, 30};
int *p = arr;
printf("*(p+1) = %d\\n", *(p+1)); // 20(偏移4字节)
printf("p[2] = %d\\n", p[2]); // 30(数组表示法)
三、指针与数组的深度互动
1. 数组指针 vs 指针数组
数组指针 | int (*p)[5] | 指向整个数组 | 用于二维数组操作 |
指针数组 | int *arr[5] | 元素都是指针 | 存储多个字符串地址 |
2. 一维数组操作
int scores[5] = {85, 90, 78, 92, 88};
int *p = scores; // 等价于 &scores[0]
// 四种访问方式等价
printf("第三位学生分数: %d\\n", scores[2]); // 78
printf("通过指针: %d\\n", *(p + 2)); // 78
printf("混合访问1: %d\\n", *(scores + 2)); // 78
printf("混合访问2: %d\\n", p[2]); // 78
3. 二维数组操作
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 数组指针声明
int (*p)[4] = matrix;
// 访问元素7 (row=1, col=2)
printf("元素7的四种访问方式:\\n");
printf("1. matrix[1][2] = %d\\n", matrix[1][2]);
printf("2. *(*(matrix+1)+2) = %d\\n", *(*(matrix+1)+2));
printf("3. *(*(p+1)+2) = %d\\n", *(*(p+1)+2));
printf("4. p[1][2] = %d\\n", p[1][2]);
内存布局:
text
matrix → [1,2,3,4] // matrix[0]
[5,6,7,8] // matrix[1]
[9,10,11,12]// matrix[2]
*(matrix+1) → 获取第二行首地址
*(*(matrix+1)+2) → 第二行第三个元素
四、C语言内存详解
1. 栈区(Stack)
-
存储内容:局部变量、函数参数
-
特点:自动分配/释放,速度快
-
示例
void function() {
int local_var = 10; // 栈区分配
} // 函数结束自动释放
2. 堆区(Heap)
-
存储内容:malloc/calloc动态分配的内存
-
特点:手动管理,生命周期由程序员控制
-
示例
int *arr = malloc(5 * sizeof(int)); // 堆区分配
free(arr); // 必须手动释放!
3. 全局/静态区
-
存储内容:全局变量、static变量
-
特点:程序启动时分配,结束时释放
-
示例:
int global_var; // 全局变量
void func() {
static int count = 0; // 静态变量
}
4. 常量区(关键区别!)
-
存储内容:字符串常量、const全局变量
-
特点:只读,不可修改
-
经典案例:
char *p1 = "Hello"; // "Hello"在常量区
char p2[] = "World"; // "World"在栈区(可修改副本)// p1[0] = 'h'; // 错误!尝试修改常量区
p2[0] = 'w'; // 正确!修改栈区副本
5. 代码段
-
存储内容:程序执行的二进制代码
-
特点:只读,存放函数体代码
五、const关键字的深度应用
1. 基础用法
const int MAX_SIZE = 100; // 常量
// MAX_SIZE = 200; // 编译错误!
2. 指针保护(四种模式)
int value = 10;
int another = 20;
// 1. 指向常量的指针(保护指向的数据)
const int *p1 = &value;
// *p1 = 100; // 错误!不能修改数据
p1 = &another; // 允许改变指向
// 2. 常量指针(保护指针本身)
int *const p2 = &value;
*p2 = 100; // 允许修改数据
// p2 = &another; // 错误!不能改变指向
// 3. 双重保护
const int *const p3 = &value;
// *p3 = 100; // 错误!
// p3 = &another; // 错误!
// 4. 应用于数组参数(安全传递)
void print_array(const int *arr, int size) {
for (int i = 0; i < size; i++) {
// arr[i]++ 会被阻止
printf("%d ", arr[i]);
}
}
3. 标准库应用
// 字符串函数原型
char *strcpy(char *dest, const char *src);
int strcmp(const char *s1, const char *s2);
// 使用示例
char src[20] = "Source";
char dest[20];
strcpy(dest, src); // src受const保护
评论前必须登录!
注册