当前位置: 首页 > news >正文

C语言学习——指针部分知识点归纳

C语言指针知识要点整理

一、指针基础概念

1. 什么是指针?

•指针是存储内存地址的变量​
•指针本身也有自己的内存地址
•通过指针可以间接访问和操作内存中的数据

2. 指针的声明和初始化

// 声明指针
int *p;        // 指向整型的指针
float *fp;     // 指向浮点数的指针
char *cp;      // 指向字符的指针
// 指针的初始化
int x = 10;
int *p = &x;   // p指向x的地址
// NULL指针
int *p = NULL; // 空指针,指向地址0

二、指针运算符

1. 取地址运算符 &

•获取变量的内存地址

int a = 5;
int *p = &a;  // p存储a的地址

2. 解引用运算符 *

•访问指针所指向地址的值

int a = 5;
int *p = &a;
int b = *p;   // b = 5
*p = 20;      // 通过指针修改a的值,现在a = 20

三、指针的运算

1. 算术运算

int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;     // p指向arr[0]
p++;              // p现在指向arr[1],地址增加sizeof(int)字节
p--;              // p指向arr[0]
p = p + 3;        // p指向arr[3]
int *q = p - 2;   // q指向arr[1]
  1. 关系运算
int *p, *q;
if(p == q)  // 比较两个指针是否指向同一地址
if(p < q)   // 比较指针地址的大小
if(p != NULL) // 检查指针是否非空

四、指针与数组

1. 数组名就是指针

int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;  // 等价于 int *p = &arr[0];
// 通过指针访问数组元素
*(arr + 2) = 10;     // arr[2] = 10
*(p + 3) = 20;       // arr[3] = 20

2. 指针遍历数组

int arr[5] = {1, 2, 3, 4, 5};
int *p;
// 方法1
for(p = arr; p < arr + 5; p++) {printf("%d ", *p);}
// 方法2
p = arr;
for(int i = 0; i < 5; i++) {printf("%d ", *(p + i));
}

五、多级指针

1. 二级指针

int a = 10;
int *p = &a;    // 一级指针
int **pp = &p;  // 二级指针,指向指针的指针
// 访问
printf("%d\n", a);    // 10
printf("%d\n", *p);   // 10
printf("%d\n", **pp); // 10

六、指针与函数

1. 指针作为函数参数(传地址)

// 交换两个变量的值
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}
int main() {int x = 5, y = 10;swap(&x, &y);  
// 传递地址return 0;
}

2. 指针作为函数返回值

// 返回数组最大值的地址
int* findMax(int arr[], int n) {int *max = &arr[0];for(int i = 1; i < n; i++) {if(arr[i] > *max) {max = &arr[i];}}return max;  // 返回指针
}

七、指针与字符串

1. 字符指针

// 字符串字面量
char *str = "Hello";  // str指向字符串常量
// str[0] = 'h';  // 错误!不能修改字符串常量
// 字符数组
char arr[] = "World";  // 可以修改
arr[0] = 'w';         // 正确

2. 常用字符串函数

char str1[20] = "Hello";
char str2[] = "World";
char *p;
p = strcpy(str1, str2);  // 字符串复制
p = strcat(str1, str2);  // 字符串连接
int len = strlen(str1);  // 字符串长度
p = strchr(str1, 'l');   // 查找字符

八、特殊指针

1. 空指针 NULL

•表示指针不指向任何有效地址
•使用前应检查是否为NULL

int *p = NULL;
if(p != NULL) {*p = 10;  // 安全访问
}

2. 野指针

•指向无效内存地址的指针
•未初始化的指针
•已释放内存的指针

int *p;           // 野指针,未初始化
*p = 10;          // 危险!可能崩溃
int *p = (int*)malloc(sizeof(int));
free(p);          // 释放内存
*p = 20;          // 野指针,危险!
p = NULL;         // 好习惯:释放后置为NULL

3. void 指针

•通用类型指针,可指向任意数据类型
•不能直接解引用,需先转换为具体类型

int a = 10;
float b = 3.14;
void *vp;
vp = &a;  // 指向int
*(int*)vp = 20;  // 需要类型转换
vp = &b;  // 指向float
printf("%f\n", *(float*)vp);

九、指针与动态内存分配

  1. 动态内存管理函数
#include <stdlib.h>
// 分配内存
int *p = (int*)malloc(10 * sizeof(int));  // 分配10个int空间
if(p == NULL) {
// 处理内存分配失败
}
// 重新分配内存
p = (int*)realloc(p, 20 * sizeof(int));  // 调整为20个int
// 释放内存
free(p);
p = NULL;  // 好习惯

十、指针与结构体

1. 结构体指针

typedef struct {int id;char name[20];float score;
} Student;
Student s = {1, "Tom", 90.5};
Student *p = &s;
// 访问成员
(*p).id = 2;    // 方式1
p->id = 3;       // 方式2(更常用)
strcpy(p->name, "Jerry");

2. 指针在结构体中的使用

typedef struct Node {int data;struct Node *next;  // 指向自身类型的指针
} Node;
// 创建链表节点
Node *createNode(int value) {Node *newNode = (Node*)malloc(sizeof(Node));newNode->data = value;newNode->next = NULL;return newNode;
}

十一、函数指针

1. 函数指针声明和使用

// 函数原型
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int main() {// 声明函数指针int (*funcPtr)(int, int);// 指向add函数funcPtr = add;printf("%d\n", funcPtr(5, 3));  // 8// 指向sub函数funcPtr = sub;printf("%d\n", funcPtr(5, 3));  // 2return 0;
}

2. 函数指针作为参数

int calculate(int a, int b, int (*operation)(int, int)) {return operation(a, b);
}int result = calculate(10, 5, add);  // 15

十二、易错点和注意事项

1. 常见错误

// 错误1:使用未初始化的指针
int *p;
*p = 10;  // 段错误
// 错误2:返回局部变量的地址
int* badFunction() {int x = 10;return &x;  // x是局部变量,函数结束就销毁
}
// 错误3:指针类型不匹配
float f = 3.14;
int *p = &f;  // 错误类型
printf("%d\n", *p);  // 输出错误

2. 最佳实践

1.初始化指针​:声明时立即初始化
2.​检查NULL​:使用前检查指针是否为空
3.​匹配类型​:确保指针类型与指向的数据类型匹配
4.及时释放​:动态分配的内存要及时释放
5.​避免野指针​:释放内存后置为NULL
6.注意作用域​:不要返回局部变量的地址

十三、练习理解

指针与数组等价性

int arr[5] = {1, 2, 3, 4, 5};
// 以下表达式是等价的:
arr[2]    ≡ *(arr + 2)    ≡ *(2 + arr)    ≡ 2[arr]
// 是的,2[arr] 是合法的C语法!

指针的指针

int a = 10;
int *p = &a;
int **pp = &p;
int ***ppp = &pp;
// 访问a的值
printf("%d\n", a);      // 10
printf("%d\n", *p);     // 10
printf("%d\n", **pp);   // 10
printf("%d\n", ***ppp); // 10
http://www.gsyq.cn/news/143571.html

相关文章:

  • 93 年 32 岁 IT 运维失业了!甲方不续约项目解散,你们有同款经历吗?
  • 直线模组:工业自动化的精度心脏
  • 2025年论文写作终极指南:8款免费AI神器,20分钟速成初稿,全学科覆盖!
  • AI元人文构想:从价值对齐到意义共生的范式革命与文明演进新路径(人机协作)
  • 【学习笔记】《道德经》第22章
  • python in visual studio 2022: for pip installing packages
  • AJAX本质与核心概念
  • 比话和其他降AI率工具有什么不同,为什么能把知网AI率降低到15%
  • 【分布鲁棒】基于Wasserstein距离的两阶段分布鲁棒简易模型附Matlab代码
  • 翻过入门的第一座小山
  • 基于知识图谱的RAG
  • YOLOv11 改进 - 注意力机制 | IIA信息整合注意力(Information Integration Attention ):精准保留空间位置信息,平衡精度与计算成本 | TGRS2025
  • 协议解析引擎横评:NLP技术哪家强?
  • PHP如何连接到Redis_PHP连接和操作Redis数据库的方法
  • 文件I/O与异常处理
  • 盐酸-N-取代苯胺类泄漏后应急处置,关键步骤要记牢!
  • CTF学习
  • 使用 Spring Boot WebClient 调用大模型 API(OpenAI、文心一言、通义千问)
  • 02. 色彩空间类型
  • Lua 字符串处理指南
  • Plotly/Dash高级可视化实战教程:从高维图表到企业级仪表盘
  • zsj_蓝桥python系列_列表补充
  • Pandas 安装指南
  • PS2025下载安装教程超详细保姆级全攻略(附安装包下载)Photoshop 2025 v26.0版本安装教程
  • 基于Vue的问诊平台管理系统0jbb3(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
  • 收藏必备!六个高含金量编程竞赛助你进大厂+网络安全学习资源大放送
  • 专家的进阶之路:技术深耕、跨界融合与个人品牌打造 - AK
  • LeetCode刷题记录—[933]最近请求次数
  • 网络安全与数据安全区别详解:黑客小白必收藏学习资源
  • C++ 继承