静态内存

变量都会申请内存,申请内存有两种方式,一种是静态内存,另外一种是动态内存。这里主要学习静态内存,静态内存的分配是由编译器实现

静态内存的好处:

程序员不需要考虑变量内存的申请和释放,因此不需要考虑是否有内存泄露。当程序域执行,会自动申请内存,当程序域执行完毕,会自动回收内存。

静态内存的坏处:

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.对于局部函数或静态内存,在程序域自动申请和释放,否则会引起内存泄露。

原文地址:https://www.cnblogs.com/jason207489550/p/6662428.html