function4-本质和函数指针
前言vs ide 可以选择x86编译和x64编译,同时一个项目它也存在两个版本
debug 版本就是常说的测试版本, bug就是漏洞的意思。
release 版本就是正常发行版本, 说明这个版本的漏洞相对于debug比较少,毕竟是先测试后发布。
正文本质debug的反汇编会多一些内容,这里使用release版本好分析。在项目-属性-c/c++-优化中关闭优化:
原则上优化肯定会带来性能上的提升,但不利于人为分析。
1234567891011#include<iostream>int Add(int a, int b){ return a + b;}int main(){ int c = Add(1, 2); return 0;}
老样子在int c那里打断点运行然后反汇编:
可以看到整体反汇编代码还是很简洁的。
同时int c = Add(1,2);的下面有一句call Add(0FC1000h)其实就是要跳转到add函数的位置
ps:我打开了显示符号名,所以call才会显示函数名,关闭显示符号名则只有后 ...
function3-左值右值
前言在C语言中什么叫左值和右值
12int a = 3;//a为左值,3为右值
左值一般是变量,在程序运行时有一个准确的地址和值,除了const的情况下一般都能修改。
右值则一般是常量或者临时对象,除非强转之类的操作,其它情况下一般不能修改
在编译报错的时候应该或多或少也见过到提示右值不可被修改
不过上述的说法也并不绝对
123int a = 1;int b = 2;a = b;
这里的右值b它是一个变量。
正文12345678910void AddSum(int a){ std::cout << a << "\n";}int main(){ int a = 10; AddSum(10 + 20); return 0;}
在正常情况下,int a = 10; 编译器把10转换成十六进制赋值给ebp-8的位置上而调用函数传参的时候使用算术表达式他也会默认先算好,可能这里函数的反汇编不明显稍微改动一下让a+10+20
这里就很清楚的看到编译器先将ebp-8 ...
function2
前言之前提到过函数是什么类型的就需要返回什么类型的值,正常变量类型都还好,当指针和引用的时候就有意思了
正文1234567int main(){ char *str; str = (char *)"你好世界"; std::cout << str; return 0;}
C语言的字符串最常用的就是数组的方式声明,反正数组的底层就是指针,所以你用指针也行。
但是在使用指针强转的时候,右值的这串中文它属于一个常量,也就是说指针指向了一块常量内存,你就没办法修改它了。如图:编译器给出了错误,就是说我们没有权限对这块内存写入。
要套娃的话就是赋给字符串然后强转再改,或者拷贝给另一个字符串,反正能得到结果是首要目标。
这里就利用自定义函数去拷贝修改返回一个想要的值。
123char* cstr(const char *str){}
拷贝函数memcpy(),不过要知道str的长度和一个跟str一样大的指针变量可以直接在cstr里面for循环求长度,也可以自定义函数,因为学的函数这块就姑且用函数了。
12345678 ...
function1
前言自定义函数的形式和大致参数已经明确,然后就是返回指针和引用之类的.
头文件
cstdarg
正文main函数的参数虽然也可以叫不定量,但是毕竟是提前规定了的。
123int Add(unsigned count, ...){}
比如实现一串不定量的数字求和,后面的参数就可以用…这种写法,但是必须要知道个数虽然后面用省略表示不定量,但是不是直接说就是数组了,函数里调用起来也挺稀奇的不过越是稀奇古怪用到的就越少,毕竟实际上没有这么多不定量的场景
1int x = Add(5,1,2,3,4,5);
调用的时候没啥特殊,但在实现部分中,如何调用...才是重点
123int Add(unsigned count, ...){ va_list arg;}
va_list其实就是一个char*类型的变量:如果直接使用char* arg也无可厚非。
然后就是传递不定量的值,因为引用了cstdarg头文件,所以可以使用封装好的
1234int Add(unsigned count, ...){ va_list arg; ...
functionTest
前言做个小测试
正文大致就是利用main函数的参数,去实现拆分参数,不使用原生支持的string功能自己写一个类似的。
filename.exe id:1 pass:123456 contry:china
不管第一个默认的文件名参数,从后面开始,挨个拆出:后面的值
123int searchChar(){}
一开始想着是不是要传递:的位置,这样直接截取:后面的就行了。
但是这样又很奇怪,因为只做了返回位置,截取还要另外实现。那好像又要两个自定义函数了,或者在main函数里实现,都是挺麻烦的。
直接返回ch[] 也不对劲,因为数组是要提前声明大小的……回头一想,数组的底层也是指针,那就返回char*类型的应该也凑合:
123char* searchChar(){}
然后就是参数,肯定要有俩,一个原字符串,一个要查询被丢弃的字符串,然后这俩肯定不用修改了,就const限定常量
123char* searchChar(const char *str, const char *findstr){}
然后进一步堆屎山: ...
function
前言函数是指一段可以直接被另一段程序或代码引用的程序或代码。也叫做子程序、(OOP中)方法。在程序设计中,常将一些常用的功能模块编写成函数,放在函数库中供公共选用。要善于利用函数,以减少重复编写程序段的工作量。
函数分为全局函数、全局静态函数;在类中还可以定义构造函数、析构函数、拷贝构造函数、成员函数、友元函数、运算符重载函数、内联函数等。
正文简而言之就是封装好的功能,通过特定方法调用。
123456789101112131415/* * 返回类型 函数名(参数,可以没有,也可以一到多个){ * 功能区,需要实现的代码 * return 返回值; //如果是void类型的函数,则不需要return * }*/int Add(int a, int b){ return a+b;}void PrintHe(char *ch){ std::cout << ch << std::endl;}
类型可以各式各样,但是要有准确结果和一定的复用性,不然写着也没啥用处 ...
string2
感言自认为不是一个努力的人……虽然这些20年在b站看过黑马的教程,甚至当时在本地也写过md的文件哈哈哈哈但是一段时间不用又落下了许多,也好在没有忘得一干二净吧……看到都能想起来,只是一些内置的方法会记不太清。回看也是两天看一点看一点,加上看视频又得自己做,然后顺便写在博客上,进度确实会慢一些。而且数据结构这一门快打工了也还没掌握……还是很惭愧的,后面要尽量补齐了。
前言也回顾了string的一些方法,然后小结一下string
正文字符串之中除了指针,编码是一个无时不刻不会头疼的问题。字符从存储:由表面的字符到计算机上的编码表,再到底层转换成二进制读取字符串的顺序是存储的逆向顺序。
常见的编码表:utf-8、utf-16、GBK、ASCII等
自制能统计带中文的字符串12345678910111213void tjsp(char *ch){ int n = 0; while (*ch++ != '\0'){ if (*ch < 0){ n++; *ch++; } else{ n+ ...
pointerString
前言C语言的字符串是通过数组实现的,数组本质上又和指针无二。那么cpp的字符串底层是否跟C语言一致
正文12char ch[] = "hello world";string str = "hello world";
在C语言里,ch现在就= ch[0]; 象征着数组首地址。但是string的构造我们还不清楚,所以通过编译器查看
12345678910#include<iostream>using std::string;int main(){ string str = "hello world"; std::cout << &str << "\n" << &str[0] << std::endl; return 0;}
原本想通过这样直接输出的,但是cout好像优化掉了&str[0],得到的还是整个字符串的值。那就粗暴点用C语言的printf指定格式输出
12printf("% ...
waline更新缓存错误
整活预览的时候发现评论突然挂了
正文
说我的Waline未定义。。。我寻思我js文件都是用的官方模板怎么就没定义了。。又上了一趟vercel.com发现也是一样控制台都是报错Waline is not defined
就很离谱啊。。。但是waline官网的看着又是正常的,就只能上github看看有没有什么类似的情况结果倒是有一个说clintv2不稳定的问题
逆天。。上一秒waline的文档里面script还是cdn的地址刷新一下又变成unpkg了
主要是相比之前的我记得好像多了个这个link,然后其他版本以前也是没写的,这次都是@v2了。。很莫名其妙啊,要我说改动就不能大改。。或者好歹发邮件提示一下。
修改了下我这个主题的ejs文件之后
评论是能看到了,版本直接跳到2.5.1了,但是之前评论的头像显示不出来控制台报错net::ERR_CONNECTION_TIMED_OUT….真是逆天。但是官网文档的好像是2.5.2。。。就很迷惑行为。而且我这里只能修改本地的配置,我在vercel那里还是访问不了,提示版本有问题未定义。。哎麻了
但是突然想 ...
string1
引用
std:string
前言回忆过C语言版的字符串
12char ch[] = "abafjiafajif";char ch[10] = "aaaaaaaa";
大致上一个意思,限定长度和不限定长度,不限定长度会自动根据初始化的值长度而定义。
其次就是拼接两个字符串
123456char ch[10] = "1234";char ch1[10] = "5678";char ch2[20];memcpy(ch2, ch, strlen(ch)); //先将ch从头拷贝进来memcpy(ch2 + strlen(ch), ch1, strlen(ch1) + 1); //在由从ch拷贝到ch2里
这样拼接起来还是挺麻烦的,如果能直接相加赋给字符串就会相对方便了。
正文12345678#include<iostream>#include<string>using std::string;int main(){ return 0;}
使用string ...