• 函数返回局部变量/局部指针


    c语言 返回局部变量 局部指针 局部数组

    内存四区模型

      讨论这个问题之前,一定要理解堆区和栈区的工作原理,数据的存储区域(参考内存四区模型),另外一定不要返回局部对象或变量的引用和指针。

    局部变量

      局部变量分局部自动变量和局部静态变量,由于c返回的是值,因此返回一个局部变量是可以的,无论自动还是静态,因为这时候返回的是这个局部变量的值。另外,函数返回局部变量时实际上是返回变量值的拷贝。a为局部变量,在栈区存储,虽然在函数调用结束后所在内存会被释放回收掉,但返回值不是访问地址,而是a的拷贝副本。

    1 int INTtest(){
    2     int a = 10;
    3     return a;
    4 }

    局部指针

      局部指针跟上面所述的局部变量一样。可以返回一个局部指针的值,也可以返回一个局部静态指针的地址,但不应该返回一个局部自动指针的地址,除非自动指针的地址指向数据区或堆区

      返回值为局部指针,可以分为:(1)声明局部变量,返回其地址;(2)声明局部数组,返回数组名;(3)声明局部指针,返回该指针。

      1.返回局部变量地址,局部变量分为自动和静态局部变量,不应该返回指向局部自动变量的指针,因为函数调用结束后栈上声明的局部自动变量被抛弃,这个指针指向一个不再存在的对象,是无意义的。但可以返回指向局部静态变量的指针,因为静态变量存在数据区,它的生存期从定义起到程序结束。

      2.返回数组名,与局部变量相同(自动和静态),调用的结果指向栈上声明的数组的首地址,函数结束后自动数组内存释放掉,将无法对其进行访问(某些编译器Release下可以访问,但理论上是没有意义的),但静态数组可以。

      3.返回指针,调用结果指向该指针指向的内存,在函数结束后在栈上声明的指针也会被释放掉,但应该注意原指针指向的内存地址,若改地址同样是栈上声明的,则无法访问,如果是数据区或堆区的内容,则可以访问。

      1和2比较容易理解,这里不再进行举例,仅对第3种情况的数据区和堆区进行说明。

      数据区:返回指针,但指针指向的内存地址存储在数据区(常量区)

     1 char * test(){
     2     char *arr = "hello world"; //字符常量
     3     //static char arr[] = "hello world!";
     4     return arr;
     5 }
     6 
     7 void  test_(){
     8     char *s = test();
     9     printf("s = %s
    ", s);
    10 }
    11 
    12 int main(){
    13     test_();
    14         return 0;      
    15 }

      堆区:返回指针,指针指向的内存地址存储在堆区,没有手动释放前都可以访问到。

     1 char *getstring(){
     2     char *p;
     3     p = malloc(100);
     4     memset(p, 0, 100);
     5     strcpy(p, "hello");
     6 
     7     return  p;
     8 }
     9 
    10 void test(){
    11     char *ret = getstring();
    12     printf("%s
    ", ret);
    13     free(ret);
    14     ret = NULL;
    15 }
    16 
    17 int main(){
    18 
    19     test();
    20 
    21     system("pause");
    22     return 0;
    23 }

      如果指针指向的内存是在函数内部申请的,基本不干返回指针这种事,做这种事情很有可能是在给自己找麻烦,多数做的都是在可以释放的地方申请好内存,通过指针传递进函数,申请和释放都在同一函数中。上面的函数,可以修改如下:

     1 void getstring01(char *p){
     2     strcpy(p, "hello");
     3 }
     4 
     5 void test01(){
     6     char *p = NULL;
     7     p = malloc(100);
     8     memset(p, 0, 100);
     9     //char *ret = NULL;
    10     getstring01(p);
    11     printf("%s
    ", p);
    12     free(p);
    13     p = NULL;
    14 }
    15 
    16 
    17 int main(){
    18         test01();
    19         return 0;
    20 }
  • 相关阅读:
    数组定义和使用
    跳转语句—break,continue,goto
    案例 天线抬不起头来
    int是几位;short是几位;long是几位 负数怎么表示
    Python3的类注意事项
    用usb线配置直流电机驱动器不能配置成功
    案例 电源灯亮,但是就是不闪灯,而且也下载不了程序
    关于ai算法的一个点子
    进程 并发 线程 032
    ftp功能深度剖析 + 线程 031
  • 原文地址:https://www.cnblogs.com/qinguoyi/p/10154804.html
Copyright © 2020-2023  润新知