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