ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

[C语言]指针知识系统总结

[C语言]指针知识系统总结 1.指针的基础定义和使用指针是C语言中存储变量内存地址(0x0000 0000-0xffff ffff---x86)的变量.通过指针可以直接访问和操作内存中的数据提高程序的灵活性和效率1.1核心定义语法一级指针数据类型* 指针名 目标变量char val a; char* p val; //p存储val的地址通过*p b可修改val的值二级指针数据类型** 指针名 一级指针char** q p; //通过**q c可间接修改val的值1.2基本操作#include stdio.h int main() { int num 10; int *p num; // 取地址 printf(num的值: %d\n, num); // 10 printf(num的地址: %p\n, num); // 地址 printf(p的值: %p\n, p); // 地址 printf(p指向的值: %d\n, *p); // *解引用 *p 20; // 通过指针修改变量值 printf(修改后num: %d\n, num); // 20 return 0; }1.3基础概念取地址符获取变量的内存地址*解引用符获取指针所指向地址中存储的值指针的大小只取决于系统架构x86(win32)--4B x64(win64)--8B1.4注意事项1单个声明中*仅绑定左侧变量char* pa, pb;中pa是指针pb是普通字符变量若需多个指针需显式加*char* pa, *pb;或用typedef简化typedef char* PChar; PChar pa, pb;两者均为指针2避免用#define定义指针类型#define PCHAR char*; PCHAR pa, pb;会被替换为char* pa, pb;仅pa是指针易出错2.const和指针结合const 与指针结合使用可以定义不同的“常量”概念增强程序的健壮性2.1指向常量的指针可以改变指向不能修改值const int* ptr; //指向常量的指针 int const* str; //等价写法2.2常量指针可以修改值不能改变指向int* const ptr var;2.3指向常量的常量指针既不能改变指向也不能修改值const int* const ptr var;2.4记忆技巧从右向左读2.5记忆口诀const在*左边修饰的是数据const在*右边修饰的是指针本身const int *p1; // p1是指向const int的指针 int *const p2; // p2是const指针指向int3.野指针和空指针野指针和空指针均会导致程序崩溃核心是避免访问无权限或不确定的内存地址3.1野指针悬挂指针指向一个无效内存地址的指针。对野指针进行解引用会导致未定义行为程序崩溃、数据损坏常见的场景有1未初始化的指针int* p;p存储随机地址直接解引用*p 1;会触发内存访问错误2指向已销毁的局部变量函数返回局部数组地址int* func(){ int arr[2]; return arr; }函数结束后arr内存释放返回的指针变为野指针int* ptr; // 未初始化野指针 free(ptr); // 释放后未置空野指针3.2空指针用NULL宏定义值为 0初始化的指针int* p NULL;。规则0 号地址内存前 128MB是系统保留区域禁止访问*p 1;会崩溃NULL的作用是明确指针 “暂时无指向”避免野指针的随机性int* ptr NULL;3.3注意事项1指针初始化要么指向有效变量int* p val;要么设为NULL。2避免强行转换固定数值为指针int* p (int*)200000;4.指针运算指针运算本质是地址的偏移偏移量由指针指向的类型决定仅在连续内存如数组中有实际意义4.1指针 ± 整型按类型偏移1核心规则指针 n等价于指针地址 n * sizeof(指针指向的类型)。例int arr[] {1,2,3,4,5}; int* p arr;arr是数组首元素地址p1偏移1*44字节int 占 4 字节指向arr[1]char* pn num;char 占 1 字节pn1偏移 1 字节。2数组访问的本质arr[i]等价于*(arr i)arr是首元素地址arr i指向第 i 个元素解引用后得到值4.2指针 - 指针计算元素个数仅当两个指针指向同一连续内存如同一数组时结果为 “两指针间的元素数量”而非地址差值。例int arr[] {1,2,3}; int* p1 arr[0], *p2 arr[2];p2 - p1 2间隔 2 个元素4.3面试高频内存大小端判断1大端模式高位字节存低地址如int val 0x12345678内存中存为0x12 0x34 0x56 0x782小端模式低位字节存低地址内存中存为0x78 0x56 0x34 0x12主流 CPUx86采用int val 0x12345678; char* p (char*)val; if (*p 0x78) printf(小端); else printf(大端); //利用 char 指针仅访问 1 字节的特性4.4基本要点递增/递减pp--加上/减去整数p np - n指针相减得到的是两个指针之间相隔的元素个数int arr[] {10, 20, 30, 40}; int *p arr; // p指向数组第一个元素 printf(%d\n, *p); // 输出10 p; // 移动到下一个int元素 printf(%d\n, *p); // 输出20 int *q arr[3]; printf(q - p %td\n, q - p); // 输出3 (相隔3个int)5.指针数组和数组指针5.1指针数组一个数组里面的每个元素都是指针int a 1, b 2, c 3; int *arr[3] {a, b, c}; // arr是一个包含3个int*的数组5.2数组指针一个指针它指向一个数组int arr[2][3] {{1,2,3}, {4,5,6}}; int (*p)[3] arr; // p是一个指针指向一个包含3个int元素的数组 // 通过p访问arr[1][2] printf(%d\n, *(*(p 1) 2)); // 输出6 // p 1 跳过一行3个int解引用后得到第2行首地址再2得到元素地址最后解引用。5.3区分技巧用 “优先级” 判断1int *arr[3]arr先与[3]结合是数组其元素是int*2int (*p)[3]p先与*结合是指针指向int [3]的数组6.指针与函数6.1指针作为函数参数void swap(int *a, int *b) { int temp *a; *a *b; *b temp; } int x 5, y 10; swap(x, y); // x和y的值被交换6.2指针作为函数返回值int* getMax(int *a, int *b) { return (*a *b) ? a : b; }切勿返回指向局部变量的指针因为函数结束后局部变量会被销毁。可以返回全局变量、静态变量或动态分配内存的指针6.3函数指针int add(int a, int b) { return a b; } int (*funcPtr)(int, int) add; // 定义函数指针并指向add函数 int result funcPtr(3, 4); // 通过函数指针调用函数result 7 // 等价于int result (*funcPtr)(3, 4);7.void*void*是一种通用指针类型可以指向任何类型的数据但不可以直接进行解引用和算术运算7.1核心特性1可接收任意类型地址int val 10; void* p val; double num 3.14; p num;无需强制转换2禁止直接操作不能解引用*p报错无法确定访问字节数不能算术运算p1报错无法确定偏移量int n 100; float f 3.14; void *vp; vp n; // 指向int printf(%d\n, *(int*)vp); // 必须先进行强制类型转换 vp f; // 指向float printf(%f\n, *(float*)vp);7.2应用实现通用函数1原理将void*强转为char*1 字节通过逐字节操作适配任意类型需传入 “数据大小”size_tvoid myCopy(void* dest, const void* src, size_t size) { char* d (char*)dest; const char* s (char*)src; while (size--) { *d *s; } // 逐字节拷贝 }2使用场景拷贝 int 数组、double 数组等任意类型数据如int arr1[3] {1,2,3}; int arr2[3]; myCopy(arr2, arr1, 3*sizeof(int));8.内存 - men 系列函数mem系列函数是标准库中操作内存的工具核心是 “直接操作字节”需区分memcpy和memmove的差异8.1memset将内存块的前size字节设为指定值int c如memset(arr, 0, sizeof(arr));数组初始化8.2memcpy从src指向的内存拷贝size字节到dest指向的内存返回dest.若dest和src内存重叠拷贝结果会出错8.3memcmp比较两个内存块的前size字节返回 0相等、正数前者大、负数后者大
返回列表