变量都会申请内存,申请内存有两种方式,一种是静态内存,另外一种是动态内存。这里主要学习静态内存,静态内存的分配是由编译器实现。
静态内存的好处:
程序员不需要考虑变量内存的申请和释放,因此不需要考虑是否有内存泄露。当程序域执行,会自动申请内存,当程序域执行完毕,会自动回收内存。
静态内存的坏处:
1.对于数组变量,有可能实际数据会大于数组长度,因此会导致数组越界;若将数组长度定义过大,实际使用很少,会导致内存的浪费。
2.对于局部函数要将结果返回给主函数,对于静态内存无法实现。
因此对于静态内存的使用,需要考虑实际场景。
针对:对于局部函数要将结果返回给主函数,对于静态内存无法实现。有如下例子:
例子1:
#include<stdio.h> #include<string.h> char* upcase(char *oldString); int main(void) { char* str1; str1 = upcase("justTest"); printf("%s ",str1); return 0; } char* upcase(char *oldString){ int counter; char *newString; strcpy(newString,oldString); for(counter=0;counter < strlen(newString);counter++){ if(newString[counter]>=97 && newString[counter] <=122){ newString[counter] -=32; } } return newString; }
执行结果:
len@DESKTOP-BDP8J2M /cygdrive/e/c_study
$ gcc staic_memory.c -o staic
len@DESKTOP-BDP8J2M /cygdrive/e/c_study
$ ./staic.exe
Segmentation fault (核心已转储)
编译没有任何警告,但是执行时直接提示段错误。
例子2:
#include<stdio.h> #include<string.h> char* upcase(char *oldString); int main(void) { char* str1; str1 = upcase("justTest"); printf("%s ",str1); return 0; } char* upcase(char *oldString){ int counter; char newString[100]; strcpy(newString,oldString); for(counter=0;counter < strlen(newString);counter++){ if(newString[counter]>=97 && newString[counter] <=122){ newString[counter] -=32; } } return newString; }
运行结果:
$ gcc staic_memory.c -o staic
staic_memory.c: 在函数‘upcase’中:
staic_memory.c:25:2: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
return newString;
^
len@DESKTOP-BDP8J2M /cygdrive/e/c_study
$ ./staic.exe
JUSTTEST`▒_
例子1和例子2的差别是局部函数upcase定义newString时,例子1用的char*,例子2是char[]
结果是例子1段错误,例子2虽然有提示返回的是局部变量的地址,但是局部函数的值依然可以返回给主函数。
从上面例子可以看到两点:
1.strcpy函数对于局部char*的拷贝存在问题(加打印发现段错误是在执行strcpy函数的时候出现)
2.strcpy函数对于source为char*,dest为char[],虽然会有警告,但是依然可以将地址给到主函数,可能有如下原因:
局部函数返回local-addr,静态内存没有释放,存在泄露
例子3:
#include<stdio.h> #include<string.h> void upcase(char *oldString,char *newString); int main(void) { char str1[100]; upcase("justTest",str1); printf("%s ",str1); return 0; } void upcase(char *oldString,char *newString){ int counter; strcpy(newString,oldString); for(counter=0;counter < strlen(newString);counter++){ if(newString[counter]>=97 && newString[counter] <=122){ newString[counter] -=32; } } }
运行结果:
len@DESKTOP-BDP8J2M /cygdrive/e/c_study
$ gcc staic_memory.c -o staic
len@DESKTOP-BDP8J2M /cygdrive/e/c_study
$ ./staic.exe
JUSTTEST
若将main函数中char[]修改为char*传递给upcase函数,依然会有段错误,在strcpy时产生段错误。
总结:
1.对于char*指针变量实例化必须是char[],否则若传入char*,会导致传入空地址或source和dest内存可能重叠,无法进行strcpy
PS:对于strcpy的学习计划后面新加随笔
2.对于局部函数或静态内存,在程序域自动申请和释放,否则会引起内存泄露。