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

做淘宝类网站的步骤优化怎么做

做淘宝类网站的步骤,优化怎么做,网站建设开发报告,ps网站参考线怎么做目录 一、const修饰指针 (一)const修饰变量 (二)const 修饰指针变量 二、野指针 (一)野指针成因 1、指针未初始化 2、指针越界访问 3、指针指向的空间释放 (二)如何规避野指…

目录

 一、const修饰指针

(一)const修饰变量

(二)const 修饰指针变量

二、野指针

(一)野指针成因

1、指针未初始化

2、指针越界访问

3、指针指向的空间释放

(二)如何规避野指针 

1、指针初始化

2、小心指针越界

3、指针变量不再使用时,及时置NULL,指针使用之前检查有效性

4、避免返回局部变量的地址

三、assert断言

四、指针的使用和传址调用

(一)strlen的模拟实现

(二)传值调用和传址调用

结语


🔥个人主页:艾莉丝努力练剑

🍓专栏传送门:《C语言》

🍉学习方向:C/C++方向

⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平



前言:前面几篇文章介绍了c语言的一些知识,包括循环、数组、函数、VS实用调试技巧、函数递归、操作符等,在这篇文章中,我将继续介绍指针的一些重要知识点!由于指针的内容较多,博主将会分为六篇博客介绍,这是第二篇!对指针感兴趣的友友们可以在评论区一起交流学习! 


 一、const修饰指针

(一)const修饰变量

变量是可以修改的,如果把变量的地址交给一个指针变量,通过指针变量的也可以修改这个变量。
但是如果我们希望一个变量加上一些限制,不能被修改,怎么做呢?这就是const的作用。

#include <stdio.h>int main()
{int m = 0;m = 20;//m是可以修改的 const int n = 0;n = 20;//n是不能被修改的 return 0;
}

上述代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n就行修改,就不符合语法规则,就报错,致使没法直接修改n。

但是如果我们绕过n,使用n的地址,去修改n就能做到了,虽然这样做是在打破语法规则。

#include <stdio.h>int main()
{const int n = 0;printf("n = %d\n", n);int* p = &n;*p = 20;printf("n = %d\n", n);return 0;
}

输出结果: 

 

                                                         程序运行结果  

我们可以看到这里一个确实修改了,但是我们还是要思考一下,为什么n要被const修饰呢?就是为了不能被修改,如果p拿到n的地址就能修改n,这样就打破了const的限制,这是不合理的,所以应该让p拿到n的地址也不能修改n,那接下来怎么做呢?

(二)const 修饰指针变量

一般来讲const修饰指针变量,可以放在*的左边,也可以放在*的右边,意义是不一样的。

int * p;//没有const修饰? 
int const * p;//const 放在*的左边做修饰 
int * const p;//const 放在*的右边做修饰

具体分析一下: 

代码1:测试无const修饰的情况

#include <stdio.h>void test1()
{int n = 10;int m = 20;int* p = &n;*p = 20;//ok?p = &m; //ok?
}

代码2:测试const放在*的左边情况 

#include <stdio.h>void test2()
{int n = 10;int m = 20;const int* p = &n;*p = 20;//ok?p = &m; //ok?
}

代码3:测试const放在*的右边情况 

#include <stdio.h>
void test3()
{int n = 10;int m = 20;int * const p = &n;*p = 20; //ok?p = &m; //ok?}

代码4:测试*的左右两边都有const 

#include <stdio.h>
void test4()
{int n = 10;int m = 20;int const * const p = &n;*p = 20; //ok?p = &m; //ok?}int main()
{//测试⽆const修饰的情况 test1();//测试const放在*的左边情况 test2();//测试const放在*的右边情况 test3();//测试*的左右两边都有const test4();return 0;
}

结论:const修饰指针变量的时候

(1)const如果放在 的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。 但是指针变量本身的内容可变。

(2)const如果放在 * 的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变。

二、野指针

概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。

(一)野指针成因

野指针的成因主要分为指针未初始化、指针越界访问、指针指向的空间释放这三种,我们这里通过代码了解一下,理由我标注在代码的注释部分哩。

1、指针未初始化
#include <stdio.h>int main()
{ int *p;//局部变量指针未初始化,默认为随机值 *p = 20;return 0;
}
2、指针越界访问
#include <stdio.h>int main()
{int arr[10] = {0};int *p = &arr[0];int i = 0;for(i = 0; i <= 11; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针 *(p++) = i;}return 0;
}
3、指针指向的空间释放
#include <stdio.h>int* test()
{int n = 100;return &n;
}int main()
{int*p = test();printf("%d\n", *p);return 0;
}

(二)如何规避野指针 

1、指针初始化
2、小心指针越界
3、指针变量不再使用时,及时置NULL,指针使用之前检查有效性
4、避免返回局部变量的地址

比如说造成野指针的第3个例子,不要返回局部变量的地址。

三、assert断言

assert.h 头文件定义了宏 assert() ,用于在运行时确保程序符合指定条件,如果不符合,就报
错终止运行。这个宏常常被称为“断言”

assert(p != NULL);

上⾯代码在程序运行到这一行语句时,验证变量 p 是否等于 NULL 。如果确实不等于 NULL ,程序继续运行,否则就会终止运行,并且给出报错信息提示。

assert() 宏接受一个表达式作为参数。如果该表达式为真(返回值非零), assert() 不会产生任何作用,程序继续运行。如果该表达式为假(返回值为零), assert() 就会报错,在标准错误流 stderr 中写入一条错误信息,显⽰没有通过的表达式,以及包含这个表达式的文件名和行号。

assert() 的使用对程序员是非常友好的,使用 assert() 有几个好处:它不仅能自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭 assert() 的机制。如果已经确认程序没有问题,不需要再做断言,就在 #include <assert.h> 语句的前面,定义一个宏 NDEBUG 。

#define NDEBUG
#include <assert.h>

重新编译程序,编译器就会禁用文件中所有的 assert() 语句。如果程序又出现问题,可以移
除这条 #define NDEBUG 指令(或者把它注释掉),再次编译,这样就重新启用了 assert() 语
句。

assert() 的缺点是,因为引入了额外的检查,增加了程序的运行时间。
一般我们可以在 Debug 中使用,在 Release 版本中选择禁用 assert 就行,在 VS 这样的集成开
发环境中,在 Release 版本中,直接就是优化掉了。这样在debug版本写有利于程序员排查问题,
在 Release 版本不影响用户使用时程序的效率。

四、指针的使用和传址调用

(一)strlen的模拟实现

库函数strlen的功能是求字符串长度,统计的是字符串中 \0 之前的字符的个数。

下面是函数原型:

size_t strlen ( const char * str );

参数str接收一个字符串的起始地址,然后开始统计字符串中 \0 之前的字符个数,最终返回长度。
如果要模拟实现只要从起始地址开始向后逐个字符的遍历,只要不是 \0 字符,计数器就+1,这样直到 \0 就停止。 

代码实现:

#define  _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>
#include<assert.h>int my_strlen(const char* str)
{int count = 0;assert(str);while (*str){count++;str++;}return count;
}int main()
{int len = my_strlen("abcdef");printf("%d\n", len);return 0;
}

(二)传值调用和传址调用

我们学习指针的目的是使用指针解决问题,那有什么问题是非指针解决不可的呢?有的兄弟,有的。我们在这里就举一个例子:要求写一个函数,能够交换两个整型变量的值。

我们尝试了一番,写出了这样的代码:

#define  _CRT_SECURE_NO_WARNINGS  1#include <stdio.h>void Swap1(int x, int y)
{int tmp = x;x = y;y = tmp;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:a=%d b=%d\n", a, b);Swap1(a, b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}

输入两个值(中间记得空格) 试试能不能行得通,输出结果:

啊嘞?这是什么情况!我们发现代码没产生实际交换的效果!这是为什么哩?

调试一下,我又给友友们请来了我们的老朋友、老军师——监视

注意:不知道监视怎么搞的友友们可以去看博主的这篇博客:VS2022进行监视功能的步骤

好啦好啦,我们话不多说,调试一下试试:

 

真相大白了,我们发现在main函数内部,创建了a和b,a的地址是0x00cffdd0,b的地址是0x00cffdc4,在调用Swap1函数时,将a和b传递给了Swap1函数,在Swap1函数内部创建了形参x和y接收a和b的值,但是 x的地址是0x00cffcec,y的地址是0x00cffcf0,x和y确实接收到了a和b的值,不过x的地址和a的地址不一样,y的地址和b的地址不一样,相当于x和y是独立的空间,那么在Swap1函数内部交换x和y的值, 自然不会影响a和b,当Swap1函数调用结束后回到main函数,a和b的没法交换。Swap1函数在使用的时候,是把变量本身直接传递给了函数,这种调用函数的方式我们之前在函数的时候就知道了,这种叫传值调用。  

由此我们可以得出结论:实参传递给行参的时候,形参会单独创建一份临时空间来接受实参,对形参的修改不影响实参。

因此Swap1战败啦。

这下子怎么办哩?!

咱们当务之急是解决调用Swap函数时,Swap函数内部操作的就是main函数中的a和b,直接
将a和b的值交换了。那么就可以使用指针了,在main函数中将a和b的地址传递给Swap函数,Swap函数里边通过地址间接的操作main函数中的a和b,并达到交换的效果就好了。

代码实现:

#define  _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>void Swap2(int* px, int* py)
{int tmp = 0;tmp = *px;*px = *py;*py = tmp;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:a=%d b=%d\n", a, b);Swap2(&a, &b);printf("交换后:a=%d b=%d\n", a, b);return 0;
}

事不宜迟,咱们赶紧测试一下!输出结果: 

我们从这里可以看到实现成Swap2的方式,顺利完成了任务,这里调用Swap2函数的时候是将变量的地址传递给了函数,这种函数调用方式叫:传址调用。 

传址调用,可以让函数和主调函数之间建立真正的联系,在函数内部可以修改主调函数中的变量;所以未来函数中只是需要主调函数中的变量值来实现计算,就可以采用传值调用。如果函数内部要修改主调函数中的变量的值,就需要传址调用。


结语

往期回顾:

C语言指针深入详解(一):内存和地址、指针变量和地址、指针变量类型的意义、指针运算

结语:本篇文章就到此结束了,本文为友友们分享了一些操作符相关的重要知识点,如果友友们有补充的话欢迎在评论区留言,下一期我们将继续介绍操作符剩下的一些重要知识点,感谢友友们的关注与支持!

http://www.dtcms.com/wzjs/9340.html

相关文章:

  • 哈尔滨做企业网站信息流推广的竞价机制是
  • 给个网站好人有好报2021建立网站的基本流程
  • 西昌新站seo百度购物平台客服电话
  • 产品详情页面设计福州seo推广外包
  • 长春自助建站模板百度发布信息的免费平台
  • 芜湖北京网站建设网络营销活动策划
  • 做h网站风险代运营电商公司
  • 网站建设制中国软文网官网
  • 微网站开发程序百度百家号官网登录
  • 企业移动网站建设宁波seo托管公司
  • 承接博彩网站建设seo整站优化外包
  • 表白网站制作器搜索引擎是网站吗
  • 绍兴专业做网站的公司谷歌paypal官网入口
  • dede网站入侵如何建立自己的网站?
  • 中国新闻社官网招聘广州seo外包公司
  • 网站设置怎么删除银川seo
  • 做私人网站 违法百度竞价排名广告定价鲜花
  • 平潭做网站如何创建微信小程序
  • 3d视频动画制作桂林网站优化
  • 济南建网站价格消费品展网络营销品牌
  • wordpress 增加css样式seo sem
  • 做网站是java还是php成都网络推广哪家好
  • 郑州建网站公司每日军事新闻
  • 可以建网站的平台中国十大网站有哪些
  • 网站建设规划书中的技术可行性不包括搜索引擎大全排行
  • 三原网站建设竞价代运营
  • 政府网站建设的创新机制南昌seo搜索排名
  • 免费素材网站 可商用大二网页设计作业成品
  • 微网站的搭建备案查询平台官网
  • xp做的网站有连接限制seo博客推广