局部變量地址的返回

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







 

發佈了73 篇原創文章 · 獲贊 18 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章