首页 > 代码库 > 局部变量地址的返回

局部变量地址的返回

char *fun()
{
char str[] = "hello";
return str;
}

这个函数的返回值?以及这个函数在栈上的存储布局

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *fun()
{
    char ptr[] = "fda";              
    int a = 3;
    int b = 4;                                                                                                                      printf("test: %x %x %d\n", ptr, &ptr[1], sizeof(ptr)); 
    printf(" ptr a b :%x %x %x\n", ptr, &a, &b);
    return ptr;
}

int main(int argc, const char *argv[])
{
    char a1 = '7';
    char *p = fun();
    char a2 = '9';
    printf("a1 a2 p(fun): %x %x  %x\n", &a1, &a2, p);
    char a = 4;
    char b = 4;
    printf("%x %x\n", &a, &b);
    return 0;
}

 就函数而言,返回局部变量的地址这种做法是错误的,但是这个函数不管是在VS还是在gcc上编译时都只会有一个警告

 局部变量的地址在出了作用域后就没有意义了,可能被其他数据覆盖


?  1009 git:(master) ? gcc test1.c
test1.c: 在函数‘fun’中:
test1.c:12:5: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
     return ptr;
     ^
?  1009 git:(master) ? ./a.out 
test:bfe416fc bfe416fd 4
ptr a b :bfe416fc bfe416f8 bfe416f4
a1 a2 p(fun): bfe4171b bfe4171a  bfe416fc
bfe41719 bfe41718

可以看看地址的分布情况:

...171b                  a1

....171a                 a2

....1719                   a

.....1718                   b                       

.....分配给fun函数栈...

...

....16ff           ptr[3    ‘\0‘

....16fe          ptr[2]   ‘a‘

...16fd           ptr[1]   ‘d‘

...16fc           ptr[0]    ‘f ‘        ---》如果字符串长度加1 不为4的倍数会有内存对齐

....16f8           int  a

....16f4          int   b


函数退出后再定义变量,又回到171a处


可以看出大致结构,给函数分配栈时并不是直接接着上面的,虽然函数退出后没有清空或者初始化刚刚函数占用的栈,但是后续的数据可以覆盖上去

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *fun()
{
    char ptr[] = "fda";
    int a = 3;
    int b = 4;
    printf(" fun :%x %x %d\n", ptr, &ptr[1], sizeof(ptr));
    printf("ptr a b :%x %x %x\n", ptr, &a, &b);
    return ptr;
}

int main(int argc, const char *argv[])
{
    char a1 = '7';
    char *p = fun();
    printf("p: %d\n", *p);
    char a2 = '9';
    printf("a1 a2 p(fun): %x %x  %x\n", &a1, &a2, p);
    char a = 4;
    char b = 4;
    printf("main a b :%x %x\n", &a, &b);
    printf("p: %d\n", *p);
    return 0;
}

结果:

 

?  1009 git:(master) ? gcc test1.c 
test1.c: 在函数‘fun’中:
test1.c:12:5: 警告:函数返回局部变量的地址 [-Wreturn-local-addr]
     return ptr;
     ^
?  1009 git:(master) ? ./a.out 
 fun :bffbedfc bffbedfd 4
ptr a b :bffbedfc bffbedf8 bffbedf4
p: 102
a1 a2 p(fun): bffbee1b bffbee1a  bffbedfc
main a b :bffbee19 bffbee18
p: -33

刚退出函数时打印的是函数中的那个字符  f对应的ascii值是102,  后面定义了2个int型 就把空间覆盖了导致输出的是-33







 

局部变量地址的返回