当前位置:   article > 正文

C语言指针基础_全局指针变量

全局指针变量

目录

内存地址

取变量地址

指针

指针的使用

指针参数


内存地址

  • CPU内存的访问   ------>   通过内存地址来读写内存数据
  1. 读数据:CPU与内存条硬件之间有个地址总线,读数据的时候CPU通过地址总线将要访问的内存地址告诉内存条,内存条回数据给CPU,这样CPU就能获取内存里面的数据
  2. 写数据:CPU通过地址总线将地址告诉内存条,内存将数据存进去
  • 对于CPU而言地址是唯一的读写内存的方式
  • 内存地址是一个整数
  • 应用程序使用的内存地址,其实不是真实的物理地址,而是操作系统映射好的虚拟的内存地址
  • 32位系统与64位系统,虚拟地址是不一样的,32位系统它的地址是由32位的二进制表示的,64为的虚拟地址是由64位的二进制数据表示的

取变量地址

  • C语言里面使用'&'来获取变量所在内存的地址
  1. // 取地址
  2. int a = 10;
  3. // 每一个变量都会有一个内存地址,
  4. // 我们怎么求的这个变量的内存地址呢?
  5. // 使用取地址符号&,地址的显示都是16进制的
  6. printf("0x%x\n", &a); // 获得这个变量的起始地址;
  7. // end
  • 32位程序内存地址是32位的,64位程序内存地址是64位的   ------>   和操作系统有关

指针

  • C语言里面存放内存地址数据的变量就是指针,对于32位程序,那么指针变量的存储空间是4个字节,对于64位程序,指针变量的存储空间是8个字节
  • 指针的实质   ------>   指针存放一个地址数据的变量,指针变量
  • 指针的定义   ------>   数据类型* 变量名称,表示这个变量存放的是所定义的数据类型的内存地址数据,也确定了指向内存的大小
  • 指针变量内存分配
  1. 指针变量定义在哪里,指针变量的内存就分配在哪里
  2. 比如是一个全局的指针变量,那么就将内存分配到我们的数据段,大小为4个字节(32Bit),如果指针变量定义为一个局部变量,那么指针变量的内存就分配到栈上
  • 指针变量就是4个字节(32位)的变量,用来存放内存地址
  1. // 32bit os
  2. int m = 0; // 申请了一个内存,名字为m, 类型为int, 4个字节;
  3. int* p = NULL; // 申请了一个内存,名字为p, 4个字节,用来存放内存地址,而且有这个变量的大小信息, int,
  4. p = &m;
  5. // end
  6. // 任何一个指针变量,存放一个有效的内存地址,
  7. // 或者是你知道的一个有意义的数据;
  8. // NULL 0x0000000 地址,是操作系统禁止访问,空地址,空指针;
  9. printf("mem size = %d\n", sizeof(p));
  10. printf("mem size = %d\n", sizeof(int*));
  11. // end

指针的使用

  • 指针变量的初始化
  1. 如果指针变量暂时没有存放任何内存的地址的数据,那么一般我们会将它初始化为NULL, 例如int* p = NULL, NULL就是指针变量里面存放的是0
  2. 通过取地址符号获取变量的地址,然后赋值给指针变量;int a; int* p = &a
  3. 给指针变量存地址的时候一定要是有意义的地址,不能乱搞
  • 通过指针读数据
  1. 取得指针变量里面存放的内存地址的数据
  2. cpu使用这个地址去访问内存,然后得到数据, 这两步通过 (*指针变量)来操作
  1. // 使用指针来访问指针指向的内存的数据;
  2. double n = 7; // 8个字节
  3. //类型* 大小取决于这个类型
  4. double* ptr = &n; // ptr 4个字节,存放了n的起始地址;
  5. // 使用ptr来访问内存数据呢?内存的起始地址,大小
  6. // *号来表示,从当前指针变量存放的内存地址开始,到当前指针数据类型的大小结束(double, 8, int 4)
  7. // 使用指针,来访问我们的内存数据:
  8. // 指针来访问内存数据两大要素:
  9. // (1) 内存起始地址;
  10. // (2) 内存的大小,所占的字节数;(指针的类型决定), sizeof(数据类型)
  11. // 定义一个指针变量 类型*
  12. printf("%lf\n", *ptr);
  13. char* ch_ptr; // *ch_ptr 内存大小为sizeof(char)
  14. short* sh_ptr; // *sh_ptr 内存大小是sizeof(short)
  15. int* int_ptr; // *int_ptr 内存大小是sizeof(int)
  16. // 普通的指针,存放地址的4个字节而已;
  17. int* *int_ptr2; // *int_ptr2 内存大小sizeof(int*) 4个字节
  18. // end
  • 通过指针来写数据
  1. 取得指针变量里面存放的内存地址数据
  2. cpu使用这个地址,将数据写入到内存里面
  • 使用指针访问内存的时候,要确保指针变量里面存放的地址是哪个内存是使用指针的关键
  • 如果指针变量里面存放的地址是一个不可控的地址数据,那么操作系统会杀掉当前的进程,抛出非法错误,比如使用存放 NULL的内存地址数据的指针
  1. char ch = 40;
  2. ch_ptr = &ch;
  3. sh_ptr = 789; // 本身是4个字节可以存放4个字节允许的数据;
  4. // printf("%d\n", *sh_ptr); // 非法的异常, sh_ptr --> 789, 然后作为内存其实地址, 2个字节的内存大小;
  5. // 789是一个被OS保护的地址,
  6. // 存放内存地址而用;
  7. void* v_ptr = &ch; // ch变量的内存地址
  8. // printf(*v_ptr); // 编译错误,void类型,没有字节大小
  9. // end

指针参数

  • 指针作为函数参数:将一个内存地址传入,函数里面就能拿到这个内存地址,通过内存地址来访问变量的内存
  • 编写函数,交换两个变量的值,分析下,指针作为参数传递的全过程
  1. int lhs = 7;
  2. int rhs = 8;
  3. swap(&lhs, &rhs);
  4. printf("lhs = %d rhs = %d\n", lhs, rhs);
  5. // 把一块内存的起始地址传递过去;
  6. static void swap(int* a, int* b) {
  7. // *a = 7, *b = 8
  8. int temp = *a; // temp = 7;
  9. *a = *b;
  10. *b = temp;
  11. }

代码练习

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. // 把一块内存的起始地址传递过去;
  5. static void swap(int* a, int* b) {
  6. // *a = 7, *b = 8
  7. int temp = *a; // temp = 7;
  8. *a = *b;
  9. *b = temp;
  10. }
  11. int main(int argc, char** argv) {
  12. // 取地址
  13. int a = 10;
  14. // 每一个变量都会有一个内存地址,
  15. // 我们怎么求的这个变量的内存地址呢?
  16. // 使用取地址符号&,地址的显示都是16进制的
  17. printf("0x%x\n", &a); // 获得这个变量的起始地址;
  18. // end
  19. // 指针
  20. // (1)指针是一个变量, 变量定义在哪里内存分配在哪里;
  21. // (2)指针是一个什么样的变量呢?是存放内存地址的变量;
  22. // (3)变量内存多大呢?内存地址有多大,32位OS-->(4个字节), 64位OS(8个字节)
  23. // (4)变量存放的是哪种数据类型的类型的地址;
  24. // 类型* 变量名称;
  25. // int* 变量int类型的变量内存地址;
  26. // char* 变量char类型变量内存地址;
  27. // void* 没有任何数据类型的,就是一个地址,没有变量的大小信息的;
  28. // 32bit os
  29. int m = 0; // 申请了一个内存,名字为m, 类型为int, 4个字节;
  30. int* p = NULL; // 申请了一个内存,名字为p, 4个字节,用来存放内存地址,而且有这个变量的大小信息, int,
  31. p = &m;
  32. // end
  33. // 任何一个指针变量,存放一个有效的内存地址,
  34. // 或者是你知道的一个有意义的数据;
  35. // NULL 0x0000000 地址,是操作系统禁止访问,空地址,空指针;
  36. printf("mem size = %d\n", sizeof(p));
  37. printf("mem size = %d\n", sizeof(int*));
  38. // end
  39. // 使用指针来访问指针指向的内存的数据;
  40. double n = 7; // 8个字节
  41. //类型* 大小取决于这个类型
  42. double* ptr = &n; // ptr 4个字节,存放了n的起始地址;
  43. // 使用ptr来访问内存数据呢?内存的起始地址,大小
  44. // *号来表示,从当前指针变量存放的内存地址开始,到当前指针数据类型的大小结束(double, 8, int 4)
  45. // 使用指针,来访问我们的内存数据:
  46. // 指针来访问内存数据两大要素:
  47. // (1) 内存起始地址;
  48. // (2) 内存的大小,所占的字节数;(指针的类型决定), sizeof(数据类型)
  49. // 定义一个指针变量 类型*
  50. printf("%lf\n", *ptr);
  51. char* ch_ptr; // *ch_ptr 内存大小为sizeof(char)
  52. short* sh_ptr; // *sh_ptr 内存大小是sizeof(short)
  53. int* int_ptr; // *int_ptr 内存大小是sizeof(int)
  54. // 普通的指针,存放地址的4个字节而已;
  55. int* *int_ptr2; // *int_ptr2 内存大小sizeof(int*) 4个字节
  56. // end
  57. char ch = 40;
  58. ch_ptr = &ch;
  59. sh_ptr = 789; // 本身是4个字节可以存放4个字节允许的数据;
  60. // printf("%d\n", *sh_ptr); // 非法的异常, sh_ptr --> 789, 然后作为内存其实地址, 2个字节的内存大小;
  61. // 789是一个被OS保护的地址,
  62. // 存放内存地址而用;
  63. void* v_ptr = &ch; // ch变量的内存地址
  64. // printf(*v_ptr); // 编译错误,void类型,没有字节大小
  65. // end
  66. int lhs = 7;
  67. int rhs = 8;
  68. swap(&lhs, &rhs);
  69. printf("lhs = %d rhs = %d\n", lhs, rhs);
  70. system("pause");
  71. return 0;
  72. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/cp456/article/detail/63284
推荐阅读
相关标签
  

闽ICP备14008679号