[常用函数列表] 字符串常用函数 c/c++中宽窄字符串函数对应关系 [新手常见问题] 1.二级指针与二维数组 2.char*pText[]和char**ppText [9-3变量生命周期和修饰符] 生命周期 函数的声明周期 起于调用,结束于调用结束 局部变量的生命周期 起于调用,结束于调用结束 main函数的生命周期 main开始==进程的开始main函数的结束==进程的结束 全局变量的生命周期 起于main调用,结束于main调用结束 修饰符 auto 含义:只能用于修饰局部变量,表示该变量存储于栈stack特点:随用随开,用完消失C中默认的局部变量,就是auto类型,所以通常将其省略c++auto自动类型 register 含义:只能修饰局部变量,原则上,将内存中的变量升级到CPU寄存器中存储,这样访问速度会更快,但由于CPU寄存器数量有限,通常会在程序优化阶段,被优化为普通auto类型,可以通过汇编代码来查看,优化过程(与平台和编译有关)特点:可以避免cpu与内存的频繁交互一般程序从内存读取数据放到寄存器进行运算运算结果写入到内存 关于各个存储部件中读写速度 硬盘:7200转内存:频率1333MHZ1600MHZ带宽=频率*64/8缓存:CPU: extern 含义:只能用于修饰全局变量,全局变量本身是全局可用的,但是由于文件是单个完成编译,并且编译是自上而下的,所以说,对于不是在本范围内定义的全局变量,要想使用必须用extern进行申明,如果不加上可能会造成重定义。特点:1.可以省略,声明在前,定义在后,不论局部还是全局。main.c:inta;other.c:inta=200;编译不会报错2.外延性某文件定义的全局变量可在其他文件使用 c语言编译是跨文件的 编译过程:单文件编译单文件每个编译成xxx.o链接所有.o文件和lib.so文件生成可执行文件xxx.out [9-4static] 修饰局部变量 特点:1.初始化值为0,且只初始化一次2.生命周期等同于程序 修饰全局变量 特点:1.全局的外延性消失,变成文件内部的全局变量也适用于函数2.存储在data段 小结问题: externinta; inta=200; 是不是同一个a? 局部变量和全局变量储存的位置有什么不同? static修饰的变量值所保存的位置在哪里才导致是累计变化的? 保存在data段中 [9-5字符串常量——9-7字符串的输入输出] 定义 是双引号括起的任意字符序列 字符串大小 看到的大小,比我们实际字面量要多一个,最后的字符’\0’,我们称为字符串结束字符,是系统对双引号引起的字符串自动加设的,而非手动干预。 字符串存储 字符串的存储,不像其它普通类型的常量自变量的存储一样,普通类型自变量通常存储在代码段(text),而字符串,则存储在数据段,且是只读数据段。也就是通常意义上的常量区,但是常量区这种说法,是不太精确的,也不提倡。 拓展 栈区(stack):临时变量,局部变量,生命周期结束即销毁堆区(heap):一些new出来的变量存储的地方特定销毁时间统一销毁,析构函数数据段(data):用来存放程序中已初始化的全局变量的一块内存区域,属于静态内存分配。代码段(text):用来存放程序执行代码的一块内存区域,只读,且不可修改。可能包含一些只读的常数变量,例如字符串常量等。bbs段:bss段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域 点击加载图片 字符数组和字符串区别 1.字符串数组(栈区)是将text区的常量字符串拷贝到栈区字符串值的改变实际上是栈的值改变字符串指针是直接指向text区常量字符串地址故不能改变text区的值2.相同点:字符数组长度大于等于字符串长度 字符串的输入输出 puts函数:printf的自带换行scanf函数:默认遇到空格结束输入,scanf('%[\n]s')遇到回车结束输入,但不检查输入长度,不安全gets函数:空格也可以读入,但不检查输入长度,不安全。fgets函数:参数列表(接收变量,长度,输入流) tips 1.printf(“”)空串有换行功能2.gets;不检查预留存储区是否能够容纳实际输入的数据,换句话说,如果输入的字符数目大于数组的长度,gets无法检测到这个问题,就会发生内存越界,所以编程时建议使用fgets。char*fgets(char*s,intsize,FILE*stream);fgets虽然比gets安全,但安全是要付出代价的,代价就是它的使用比gets要麻烦一点,有三个参数。它的功能是从stream流中读取size个字符存储到字符指针变量s所指向的内存空间。它的返回值是一个指针,指向字符串中第一个字符的地址。3.c中允许c++不允许chara[2]='china';printf('%s',a);输出结果:ch4.char*p='china';printf('p=%pp+1=%pp[0]=%c0[p]=%c\n',p,p+1,p[0],0[p]);printf('=%p=%p=%c=%c\n','china','china'+1,'china'[0],0['china']);输出结果:地址不相等与视频不符合 问题? 1.视频说'字符串,则存储在数据段'·1 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等 2.字符串指针和字符数组的区别?字符数组可修改内容,有个拷贝过程,data段常量区拷贝到栈区,字符数组实际是栈区字符串指针如果指向data段字符串常量是不可修改地址的,若是指向字符数组反而可以 [10-2从字符串常量到字符数组] [10-3原生字符串处理] strlen(char*)字符串长度 strcat(char*head,char*tail)连接两个字符串 注意:被连接的串必须有足够空间 butvs可行… charfirstName[]='jim';charfamilyName[30]='tim';strcat(firstName,familyName);printf('%s',firstName);输出:jimtim 优化操作: 原本代码 while(*p)p++;char*p,*q;while(1){p*=q*;if(p*=='\0'){break;}p++;q++;}优化后:while(*p)p++;while(*p++=*q++); Tip int*和char*,float*长度是多少? 指针统一长度为4byte inta=1;int*ap=&a;printf('%d\n',sizeof(ap));char*c='123';printf('%d\n',sizeof(c));floatd=1.0f;float*dp=&d;printf('%d\n',sizeof(dp));输出:444 char*ac=“123”; printf('%p\n',&ac); printf('%p\n',“123”); 为什么输出地址不同? 3.字符串长度和大小是不同的 长度是指字符长度且不包含\0,大小是指字节大小包含\0 [10-7字符串指针数组入门] 指针数组的本质是数组,数组指针的本质是指针。 Tips 1.运行这段代码设置字符串池优化 char*pa='china';char*pb='america';char*pc='canada';char*pd='japan';char*cpArr[4]={pa,pb,pc,pd};printf('pa=%p\n',pa);printf('pb=%p\n',pb);printf('pc=%p\n',pc);printf('pd=%p\n',pd);for(inti=0;i<4;i++){printf('%p\n',cpArr[i]);}printf('----------------\n',pd);char*cpArr2[4]={'china','america','canada','japan'};for(inti=0;i<4;i++){printf('%p\n',cpArr2[i]);} NULL,nullptr,0区别 [11-1栈内存和堆内存的基本概念] 概念 源程序:源代码 程序:可执行文件 进程:时间概念可执行性文件被拉起,到结束的这一段过程,称为进程 进程空间:可执行文件被拉起以后在内存中的分布情况 点击加载图片 栈内存 栈存储的特点 栈中存放任意类型的变量,但必须是**auto**类型修饰的,即自动类型的局部变量,随用随开,用完即消。内存的分配和销毁系统自动完成,不需要人工干预。分配顺序,由高地址到低地址。 栈的大小 栈的大小并不大,他的意义并不在于存储大数据,而在于数据交换。 常见栈溢出 局部变量申请过多,过大,char[1024*1024*10];递归层数太多例如10000层递归 堆内存 栈存储的特点 堆内存可以存放任意类型的数据,但需要自己申请与释放。分配顺序,由低地址到高地址。 堆大小 堆大小,想像中的无穷大,对于栈来说,大空间申请,唯此,无它耳。但实际使用中,受限于实际内存的大小和内存是否连续性。(基本最大为用户空间大小) Tips 1.memset(pm,1,10*sizeof(int); 为每个字节赋值为1;一个int实际4个字节4个0x01printf('%#x');%#表示的输出提示方式,如果是8进制,在前面加0,如果是十进制,不加任何字符,如果是十六进制,会加上0x 2.calloc和malloc calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不做初始化,分配到的空间中的数据是随机数据 3.realloc void*realloc(void*ptr,size_tsize); 功能:扩容(缩小)原有内存的大小。通常用于扩容,缩小会会导致内存缩去的部分数据丢失。 参数: void*ptr:ptr表示待扩容(缩小)的指针,ptr为之前用malloc或者calloc分配的内存地址。或ptr==NULL,则该函数等同于malloc。 size_t:size表示扩容(缩小)后内存的大小。 返回值: 成功返回非空指针指向申请的空间,失败返回NULL。返回的指针,可能与ptr的值相同,也有可能不同。若相同,则说明在原空间后面申请,否则,则可能后续空间不足,重新申请的新的连续空间,原数据拷贝到新空间,原有空间自动释放。 原理:先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。 malloc使用流程申请判空使用释放置空 问题1:指针接收创建的内存空间(malloc),释放时怎么知道释放(free)多少内存空间的 heap的每个块儿头有保存本块的大小以及本块分配的大小。 free并不知道那个指针所指空间的大小,它要先查找当前heap的头部,然后整个块儿释放掉。 问题2:如何用malloc/new定义一维,二维,三维数组?用free/delete销毁呢?malloc/free和new/delete区别? 问题3:malloc/calloc/realloc区别与不同? 问题4:常见的内存泄露和检测内存泄露的常见方式?内存泄漏和野指针? |
|