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

深圳市盐田区建设局网站天元建设集团有限公司法定代表人

深圳市盐田区建设局网站,天元建设集团有限公司法定代表人,wordpress自定义分类法,网站的建设与颜色搭配1.指针是什么#xff1f; 理解指针的两个要点#xff1a; 1.指针是内存中一个最小单元的编号#xff0c;也就是地址 2.口头语中说的指针#xff0c;通常是指指针变量#xff0c;是用来存放内存地址的变量 总结#xff1a;指针就是地址#xff0c;口语中说的指针通常是指…1.指针是什么 理解指针的两个要点 1.指针是内存中一个最小单元的编号也就是地址 2.口头语中说的指针通常是指指针变量是用来存放内存地址的变量 总结指针就是地址口语中说的指针通常是指针变量。  用图理解如下 内存的最小单元是一字节对每一字节去编号对应的就是指针地址。  #include stdio.hint main() {int a 5;//是向内存中的栈空间申请4个字节的空间这4个字节用来存放5这个数值int* pa a;//pa存的是a的首地址第一个字节的地址return 0; } 这里指针变量pa存放了变量a的首地址0x00112233(假设是这个地址)。指针变量是用来存放地址的变量。存放在指针中的值都会被当成地址处理。 所以这里的问题是 一个小单元到底是多大1个字节 如何编址 经过仔细计算和权衡我们发现一个字节给一个对应的地址是比较合适的。 对于32位机器假设有32根线那么假设每根地址线在寻址的时候产生高电平高电压和低电平低电压就是1或者0那么32根地址线产生的地址就会是 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 ... 11111111 11111111 11111111 11111111 这样就能找到我们的内存单元。一共2^32个地址对应这么多个字节所以2^32字节的空间是4GB空间。同理如果是64位机器那就是2^64字节空间。 在32位的机器上地址是32个0或者1组成的二进制序列那地址就得用4个字节来存储所以一个指针变量的大小就应该是4个字节         在64位机器上如果有64根地址线那一个指针变量的大小就是8字节才能存放一个地址。 总结指针变量是用来存放地址的地址是唯一标识一个内存单元的指针变量的大小在32位平台上是4个字节在64位平台上是8个字节。 注意语法上:int* p和int *p都是可以的。int *p, *q当这样连续定义好几个指针时需要这样写*q的*是不能省略的int* 也是但最好分开定义一行定义一个指针变量分开初始化。 2.指针和指针类型 目前我们对指针的应用大多停留在取地址解引用*- 2.1指针类型  既然这些指针类型的大小都是4x86或者8x64平台那为什么不用一个通用性指针ptr_t p来代替这么多些个指针类型呢C语言没有这样设计是因为不同类型的指针是有区别的- 2.2指针的解引用操作 #include stdio.hint main() {int a 0x11223344;int* pa a;*pa 0;return 0; } 我们按F11调试看看这段代码在内存中发生了什么-  我们关闭监视窗口打开内存并显示4列- 在地址那块我们能输入a就能出现对应的a的地址。我们能看到a初始化完在内存中是这样存储的我们再看*pa 0会发生啥- 这个*pa 0操作把内存中的四字节空间全部变成了0。  #include stdio.hint main() {int a 0x11223344;/*int* pa a;*pa 0;*/char* pa a;*pa 0;return 0; } char* 和int* 的大小都是同样大的都能存放a的地址那这样会发生什么呢- 我们发现这次操作只改了这四个字节的一个字节。我们这两段代码唯一不同的地方就是一个是int*一个是char*在解引用的时候一个是访问了四个字节另一个是访问了一个字节。因此指针类型是有意义的指针类型决定了指针进行解引用操作的时候访问几个字节。一个char*的指针在解引用的时候访问了一个字节。一个int*的指针在解引用的时候访问了四个字节。因此如果我们想从某个地址向后访问一个字节就可以解引用char*访问四个字节可以解引用int*。当我们想从某个地址向后访问两个字节的时候可以使用short*类型的指针。 虽然有个小警告a的类型是int*的两边类型不一致编译器弹出了警告不想看到这个警告可以把a强制类型转换为char*。  #include stdio.hint main() {int a 0;int* pa a;char* pc a;printf(pa %p\n, pa);printf(pa 1 %p\n, pa 1);printf(pc %p\n, pc);printf(pc 1 %p\n, pc 1);return 0; } 很明显如果是一个int*的指针1跳了四个字节而char*的指针1跳了一个字节。因为指针类型的不一样导致1出现不同的结果int*的指针指向的变量是一个int类型的变量它1就跳过四个字节的空间char*的指针指向的是一个char类型的变量它1就跳过了一个字节的空间。 所以指针类型是有意义的。指针类型决定了指针1/-1跳过了几个字节。 char*的指针1跳过1个字节 short*的指针1跳过2个字节 int*的指针1跳过4个字节 double*的指针1跳过8个字节 总结指针的类型决定了指针向前或者向后走一步有多大距离。 这样访问起来就比较舒服了不管是解引用一次还是跳过一次都是一个整形一个整形访问的。假设也有一个short*的指针也找到了首元素地址那个位置这样访问两个字节和1跳过两个字节就比较别扭了就不合适循环十次才访问了五个整形空间。拿一个int*的指针循环十次就能访问完。如果你就是想一个字节一个字节访问那也可以拿char*指向那个地址一字节一字节的访问也是ok的。想以什么方式去访问就应该拿什么样的指针去访问。 -int*一次修改四字节空间。 -char*一次修改一字节空间。 在内存中只要我们得到一个地址我们就能利用指针对其进行向前后者向后的访问。 3.野指针 概念野指针就是指针指向的位置是不可知的随机的、不正确的、没有明确限制的。 eg: #include stdio.hint main() {int* p (int*)0x11223344;*p;return 0; } 这个0x11223344是一个随便捏造的地址然后访问这段未知空间这是不合适的是很危险的就像有人给你打骚扰电话一样。  3.1野指针成因 1.指针没有初始化 #include stdio.hint main() {int* p;*p 20;return 0; } 在vs2022下直接报错。  因为局部变量p未初始化默认为随机值。  2.指针越界访问 #include stdio.h int main() {int arr[10] { 0 };int* p arr;int i 0;for (i 0; i 10; i){//当指针指向的范围超出数组arr的范围时p就是野指针*p i;p;}return 0; } 上述*p i;p可以写成*p因为优先级的原因先和p结合所以是*p假设p的值为0x1122344*对后面p这个表达式解引用这个表达式的值是0x11223344但先进行计算的是p此时p变成了0x11223348。也可以简单理解为先使用p再。 3.指针指向的空间释放 #include stdio.hint* test() {int a 0;return a; }int main() {int* p test();printf(%d\n, *p);return 0; } 虽然报的是警告但这里还是挺致命的当test函数结束的时候局部变量a就要被销毁空间就会被回收这个时候访问一个被回收的空间就是野指针为啥说它致命呢当这个函数结束时这块内存空间会被回收但如果这时这块空间又被申请了你的p指针还指向那块空间你以为还是a。有点像你去租房子上一间租客还留着钥匙万一发疯当自己房子拿钥匙开门了那不就完蛋了吗。 动态内存开辟的时候会仔细讲解现在只是提一下。 3.2如何规避野指针 1.指针初始化 2.小心指针越界 3.指针指向的空间释放及时置NULL 4.避免返回局部变量的地址 5.使用指针之前检查有效性 如果明确知道指针应该指向哪里就指向正确的地址如果不知道指针初始化什么值为了安全初始化为空指针NULL本质是0。 0作为地址时用户程序是不能访问的 #include stdio.hint main() {int* p NULL;if (p ! NULL){//...}return 0; } 在使用指针之前可以检查指针的有效性。 至于为什么要增加一个宏定义NULL是为了可读性虽然在值上二者是相等的并且int* p 0;也没问题但可读性没那么高0可以表示的东西多多了。一但发现一个东西被赋值NULL那一定知道这个东西是个指针。 4.指针运算 1.指针-整数 2.指针-指针 3.指针的关系运算 #include stdio.hint main() {int arr[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* p arr;for (int i 0; i 10; i){printf(%d , *(p i));//p指向的是数组首元素//pi是数组中下标为i的元素的地址//pi其实是跳过了i*sizeof(int)个字节}return 0; } 观察易得知  arr p;它两都是数组首元素的地址 arri pi *(arri) *(pi) arr[i]//都是数组第i个元素 *(arri) arr[i] *(iarr) i[arr] 所以[]仅仅只是个操作符他和一样支持操作数的交换律。同时也说明arr[i]只是数组第i个元素的表示形式编译器在处理的时候会转化为*(arri)可以简单理解为语法糖吧。 这就是数组第i个元素访问的本质——数组名是个地址i是个偏移量。不信的话看看p[i]; 本质都是一个地址加一个偏移量就能得到一个新地址对其解引用就能访问了。其实这里并不是教大家去学“茴”的四种写法而是知道原来指针的偏移量和数组元素的访问是有关系的。其实还就是地址、偏移量、解引用等一系列操作。 在指针的关系运算中- #define N_VALUES 5 float values[N_VALUES]; float *vp; for(vp values[N_VALUES]; vp values[0];) {*--vp 0; } for(vp values[N_VALUES-1]; vp values[0];vp--) {*vp 0; } 实际在绝大部分的编译器上是可以顺利完成任务的然而我们还是应该避免第二种写法因为标准并不保证它可行。 标准规定 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。 第二种写法出循环的时候指针已经指向了第一个元素之前的那个内存位置并且是做了比较的。可能是因为推测当向内存申请40字节空间时其实操作系统会多给你一块空间用来存你申请了多少字节空间。此时来说向后越界比向前越界相对安全。 #include stdio.hint main() {int arr[10] { 0 };printf(%d\n, arr[9] - arr[0]);return 0; } 指针-指针的前提是两个指针指向同一块区域指针类型也是相同的得到的是指针和指针之间的元素个数。 小地址-大地址为负的元素个数。 之前在函数那章节写过两种模拟实现strlen一种是计数器另一种是递归初阶C语言-函数-CSDN博客现在利用这个特性可以模拟实现一下strlen- #include stdio.hsize_t My_strlen(char* str) {char* start str;//记录初始位置while (*str ! \0)str;return str - start; }int main() {char arr[] abcdef;size_t len My_strlen(arr);printf(%zd\n, len);return 0; } \0也是一个字符是八进制形式\ddd它的ascii码值是0。 5.指针与数组 指针就是指针指针变量就是一个变量存放地址指针变量的大小是4/8字节 数组就是数组可以存放一组数数组的大小取决于元素个类型与个数 联系就是 数组的数组名是数组首元素地址地址是可以存放在指针变量里面中。 #include stdio.hint main() {int arr[] { 1, 2, 3, 4, 5 };printf(%p\n, arr);printf(%p\n, arr[0]);return 0; } 绝大多数情况下数组名表示数组首元素的地址有两个例外- 1.sizeof 数组名数组名单独放在sizeof内部计算数组的大小单位是字节。 2.数组名这里的数组名表示整个数组取出的是数组的地址数组的地址和数组首元素的地址值是一样的但类型和意义是不一样的。类似char* p1 0x1122int* p2 0x1122。 #include stdio.hint main() {int arr[10] { 0 };printf(%zd\n, sizeof arr);printf(%p\n, arr);printf(%p\n, arr);return 0; } arr1跳过的是数组一个元素的地址arr1跳过的是arr一个数组的地址- 这里也能说明二者的指针类型是不一样的。  6.二级指针 指针变量也是变量也有自己的地址于是我们能用指针变量去存指针变量的地址这就是二级指针。  #include stdio.hint main() {int a 10;int* p a;int** pa p;return 0; } p是指针变量一级指针变量pa也是指针变量二级指针变量还可以有三级四级...指针变量。 7.指针数组 指针数组是指针还是数组呢答案是数组类比字符数组整型数组字符和整型是类型重点是数组。 字符数组——存放字符的数组        char arr[7]; 整型数组——存放整型的数组        int arr[8]; - 指针数组——存放指针的数组        char* arr[7];or int* arr[7];等等 #include stdio.hint main() {//用指针数组来模拟二维数组int arr1[] { 1, 2, 3, 4, 5 };int arr2[] { 2, 3, 4, 5, 6 };int arr3[] { 3, 4, 5, 6, 7 };int* arr[] { arr1, arr2, arr3 };for (int i 0; i 3; i){for (int j 0; j 5; j){printf(%d , arr[i][j]);}printf(\n);}return 0; } 这只是模拟二维数组并不是真的二维数组因为二维数组的内存分布是连续的这个内存分布是不连续的。
http://www.w-s-a.com/news/395411/

相关文章:

  • 私人做网站要多少钱展芒设计网页
  • 怎样网站制作设计如何在网上推广农产品
  • 做关键词排名卖网站聚名网
  • 吉林省住房城乡建设厅网站首页体育器材网站建设方案
  • 网站建设及维护专业手机金融界网站
  • 常州网站建设工作室建立网站有怎么用途
  • 如何盗取网站推广策划书模板
  • 游戏网站建设计划书网络开发需要学什么
  • 手机网站维护费网站开发包括网站过程
  • 懂做游戏钓鱼网站的网站建设技术的发展
  • 网站被百度收录百度一下你就知道 官网
  • 雅客网站建设做网站用什么做
  • 做宣传海报网站专业网站设计速寻亿企邦
  • 秦皇岛市住房和城乡建设局网站有关网站开发的参考文献
  • 晋城城乡建设局网站深圳外贸业务员工资
  • 招聘网站开发的公司销售运营主要做什么
  • 徐州网站无障碍建设wordpress证书
  • c语言可以做网站吗请人做网站收费多少
  • 中英双语网站怎么做网站为什么做静态
  • 毕业设计做音乐网站可以吗网站运营方案
  • windos 下做网站工具网站右侧返回顶部
  • 点餐网站怎么做济源网站建设济源
  • 嘉兴公司网站制作文明网站的建设与管理几点思考
  • 扬州公司做网站徐州网站建设优化
  • 手机网站弹出层插件有哪些wordpress 文章标签
  • 网站建设详细合同范本长沙注册公司流程与费用
  • 搜索引擎网站录入wordpress怎么修改导航
  • 业务接单网站重庆网站制
  • 绿色农产品网站景区网站建设策划方案
  • 服务器做ssr后还可以做网站吗品牌形象设计公司