指针简介
指针(Pointer)是C语言的一个重要知识点,其使用灵活、功能强大,是C语言的灵魂
指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问
指针生活实例化
指针的本质是地址,在生活中比如你取快递时的快递单号,所发的位置地址,比如中国北京清华大学,这个就是地址,在生活中int(c语言的基本类型),就好比装water的容器,int a=0;可以这么理解有一个int类型的水杯,它的名字叫a,里面存放0这个水,但是我们如果想让舍友帮忙拿一下水杯,我们可以怎么说“哥们帮我拿一下我的水杯,在咱们宿舍里,我的桌子上”,其中“我的水杯(水杯类型的指针),在咱们宿舍里,我的桌子上”这个就是目前我的水杯的地址==(int *p=&a),这就是指针的实例化
计算机存储机制
int a = 0x12345678;
short b = 0x5A6B;
char c[ ] = {0x33, 0x34, 0x35};
指针
定义指针
指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针 定义一个指针变量:
在定义指针时,它分配的字节大小是由计算机本身决定的,32位操作系统分配四个字节,64位操作系统分配8个字节
指针的操作
若已定义:
int a; //定义一个int型的数据
int *p; //定义一个指向int型数据的指针
q++理解:指向下一个(相邻的内存地址)char类型数据的地址,在内存中移动了sizeof(char)个位置
d++理解:指向下一个(相邻的内存地址)int类型数据的地址,在内存中移动了sizeof(int)个位置
其实可以等效理解为数组q++指向下一个存储单元
数组与指针
数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于申请内存、定义指针和初始化
例如: char c[ ] = {0x33, 0x34, 0x35};
等效于: 申请内存
定义 char *c = 0x4000;
初始化数组数据
利用下标引用数组数据也等效于指针取内容。
例如: c[0]; 等效于: *c;
c[1]; 等效于: *(c+1);
c[2]; 等效于: *(c+2);
#include <stdio.h>
#include <stdlib.h>int main(void) {//第6页示例代码int *e;e=(int*)malloc(3*4);printf("(int*)malloc(3*4)= %x\n", (int*)malloc(3*4));//把分配到的首地址给e*e=10;*(e+1)=20;*(e+2)=30;printf("%d\n", *e);printf("%d\n", *(e+1));printf("%d\n", *(e+2));free(e);int n[]={1,2,3};printf("n[0]= %d\n", n[0]);printf("n[1]= %d\n", n[1]);printf("n[2]= %d\n", n[2]);printf("*n= %d\n", *n);printf("*(n+1)= %d\n", *(n+1));printf("*(n+2)= %d\n", *(n+2));char str[] = "Hello, World!";printf("%s\n", str);printf(str);return 0;
}
malloc:属于 #include <stdlib.h> 中的方法分配一个3*4这么大的内存空间,同时把它强转为int*类型,在使用完malloc之后要使用free();释放空间
数组的底层就是指针的操作,数组名e就是数组的地址,也是数组的第一元素的首地址
字符串的底层是数组
在底层,实际存储的时候,c语言还是会帮我们把字符串"abc"转换成字符数组进行保存,并且在未尾还要再加上"\0"
注意事项
在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预知的错误 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告
指针的应用
传递参数
使用指针传递大容量的参数,主函数和子函数使用的是同一套数据,避免了参数传递过程中的数据复制,提高了运行效率,减少了内存占用
使用指针传递输出参数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计
#include <stdio.h>// 函数:计算和与差
void calculate(int a, int b, int *sum, int *difference) {*sum = a + b; // 计算和*difference = a - b; // 计算差
}int main() {int x = 10;int y = 5;int result_sum; // 存放和int result_diff; // 存放差// 调用函数calculate(x, y, &result_sum, &result_diff);// 输出结果printf("Sum: %d\n", result_sum);printf("Difference: %d\n", result_diff);return 0;
}
传递返回值
将模块内的公有部分返回,让主函数持有模块的“句柄”,便于程序对指定对象的操作
#include <stdio.h>
#include <stdlib.h>// 定义一个结构体作为句柄
typedef struct {int *data; // 动态数组指针int size; // 数组大小
} ArrayHandle;// 模块函数:创建动态数组
ArrayHandle createArray(int size) {ArrayHandle handle;handle.data = (int *)malloc(size * sizeof(int));handle.size = size;// 初始化数组for (int i = 0; i < size; i++) {handle.data[i] = i + 1; // 示例初始化}return handle; // 返回句柄
}// 模块函数:释放动态数组
void freeArray(ArrayHandle *handle) {if (handle->data != NULL) {free(handle->data);handle->data = NULL; // 避免悬空指针}
}// 模块函数:打印数组
void printArray(ArrayHandle handle) {for (int i = 0; i < handle.size; i++) {printf("%d ", handle.data[i]);}printf("\n");
}int main() {// 创建动态数组句柄ArrayHandle myArray = createArray(5);// 打印数组内容printArray(myArray);// 释放动态数组freeArray(&myArray);return 0;
}
直接访问物理地址下的数据
访问硬件指定内存下的数据,如设备ID号等
将复杂格式的数据转换为字节,方便通信与存储
关于CLion的安装可以参考CLion安装、配置、使用、调试(完全小白向)-CSDN博客。