欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > C语言指针

C语言指针

2025/3/26 11:15:00 来源:https://blog.csdn.net/maomi_9526/article/details/146470054  浏览:    关键词:C语言指针

目录

深入理解指针(精华笔记)

一、内存与地址的本质

编址与地址总线

二、指针基础概念与运算符

指针的定义与使用

指针变量的大小

三、指针类型与意义

四、const修饰指针的用法

五、指针运算的本质

常见的指针运算

六、数组名的本质与数组传参

数组名本质

数组传参本质

七、冒泡排序与数组指针应用实例

冒泡排序算法(优化版本)

八、高级指针:二级指针与指针数组

二级指针

指针数组

九、指针数组模拟二维数组

十、指针安全(野指针与assert断言)

野指针产生原因与规避方式

断言(assert)应用

十一、传值调用与传址调用


深入理解指针(精华笔记)

一、内存与地址的本质

  • 内存:计算机内存划分为多个单元,每个单元大小为1个字节(byte)。
  • 地址:每个内存单元都有一个编号,即地址(类似宿舍门牌号)。

编址与地址总线

  • 计算机硬件通过地址总线实现编址:
    • 32位机器 → 32根地址线 → 地址长度4字节(32bit)
    • 64位机器 → 64根地址线 → 地址长度8字节(64bit)
  • CPU通过地址总线与数据总线访问内存数据。

二、指针基础概念与运算符

指针的定义与使用

  • 取地址运算符(&)

    int a = 10;
    int *pa = &a; // 指针变量pa存储a的地址
    
  • 解引用运算符(*)

    • 通过地址访问或修改数据
    *pa = 20; // 修改a为20
    

指针变量的大小

  • 指针大小由地址线宽度决定:
    • 32位平台:4字节
    • 64位平台:8字节
  • 与指针所指类型无关,同平台下指针变量大小相同。

三、指针类型与意义

  • 指针类型决定

    • 解引用权限(访问字节数):
      • char* 一次访问1字节
      • int* 一次访问4字节
    • 指针算术运算的步长(±整数运算):
      • char* 类型指针+1:地址+1字节
      • int* 类型指针+1:地址+4字节
  • 泛型指针(void*

    • 能指向任意类型数据
    • 不能直接解引用,不能指针±整数运算
    • 常用于泛型函数参数

四、const修饰指针的用法

写法含义
const int *p指针指向的内容不可改,指针可改
int *const p指针本身地址不可改,内容可改
const int *const p指针本身及指向内容都不可改

五、指针运算的本质

常见的指针运算

  • 指针 ± 整数
    • 常用于遍历数组
    *(p+i) 等价于 p[i]
    
  • 指针 - 指针
    • 常用于求元素间距离,如字符串长度
    strlen实现: return p - s;
    
  • 指针关系运算
    • 比较指针地址,常用于遍历数组判断结束

六、数组名的本质与数组传参

数组名本质

  • 数组名本质是数组首元素地址,但有两个例外:
    • sizeof(数组名):表示整个数组大小
    • &数组名:取出的是整个数组的地址,&数组名+1 会跳过整个数组大小
  • 其余任何地方,数组名都表示首元素地址

数组传参本质

  • 一维数组传参本质上传递的是首元素地址
  • 形参可以写作数组形式或指针形式:
void func(int arr[]) // 等价于 int *arr
  • 函数内部无法直接获取数组元素个数,需额外传入元素个数。

七、冒泡排序与数组指针应用实例

冒泡排序算法(优化版本)

void bubble_sort(int arr[], int sz) {for(int i=0; i<sz-1; i++) {int flag = 1; // 假设已排序for(int j=0; j<sz-i-1; j++) {if(arr[j] > arr[j+1]) {int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp;flag = 0; //发生交换,非排序状态}}if(flag) break; // 无交换则停止排序}
}

八、高级指针:二级指针与指针数组

二级指针

  • 指针变量的地址存放在另一个指针中形成二级指针:
int a = 10;
int *pa = &a;
int **ppa = &pa;
  • 二级指针解引用
    • *ppa → 得到pa(一级指针)
    • **ppa → 得到a(原数据)

指针数组

  • 存放多个指针的数组:
int a=1, b=2, c=3;
int* parr[] = {&a, &b, &c};

九、指针数组模拟二维数组

  • 指针数组元素可指向多个一维数组
int arr1[] = {1,2,3};
int arr2[] = {4,5,6};
int *parr[] = {arr1, arr2};for(int i=0; i<2; i++) {for(int j=0; j<3; j++)printf("%d ", parr[i][j]);
}
  • 内存不连续,模拟二维数组访问模式。

十、指针安全(野指针与assert断言)

野指针产生原因与规避方式

  • 原因:
    • 指针未初始化
    • 指针越界访问
    • 访问已释放空间的指针
  • 规避:
    • 初始化指针为NULL
    • 使用前检查有效性(断言)
    • 避免返回局部变量地址

断言(assert)应用

  • 检查运行时条件
assert(p != NULL);
  • 调试时开启,发布时禁用(#define NDEBUG禁用)

十一、传值调用与传址调用

  • 传值调用:修改形参不影响实参(值拷贝)
  • 传址调用:函数形参接收实参地址,间接修改实参本身
void Swap(int *x, int *y) {int tmp = *x; *x = *y; *y = tmp;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词