歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C語言的函數返回值

一:背景

談到C語言的函數返回值,可能會感覺很親切,不就是一個函數返回值嘛,當初學C語言的時候早就學過了很easy嘛,我曾經也是這麼想的。後來要上研究生了,研究生階段搞得就是C,所以又重新開始學習C,學習C的過程中遇到了很多問題,在此博客中一一記錄。實際過程中遇到的第一個問題自然就是函數返回值了。如果有人問你在一個函數中聲明一個字符串數組,最後再return這個數組。這可以實現嘛?如果是問我我可能會毫不猶豫的說OK。那事實呢?由此本文誕生了......

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

二:問題

先看幾個實際的例子:


#include<stdio.h>

#include<stdlib.h>

char *return_arry();

int main ( int argc, char *argv[] )

{

 

        printf("%s\n",return_arry());

        printf("%d\n",return_var());

        return EXIT_SUCCESS;

}

/* ----------  end of function main  ---------- */

 

 

char* return_arry ( )

{

        char str[]="zhangyifei";

        return str;

}

/* -----  end of function return_arry  ----- */

 

 

int  return_var (  )

{

        int a = 5;

        return a;

}

/* -----  end of function return_var  ----- */

 

linux 下gcc編譯報錯如下:

return.c: In function ‘return_arry’:

return.c:35:2: warning: function returns address of local variable [-Wreturn-local-addr]

  return str;

  ^

可見函數中是無法返回一個局部變量數組的。那為何return_var中沒有報錯呢。

其原因在於return a 其本質是返回了a的值,而return str則是返回了這個數組的首地址。然後str是一個局部變量,函數結束後這個地址就會被釋放掉。所以gcc提示。對於這類問題,我們要明確函數返回的是什麼,如果是值的話沒有關系,如果是地址的話,要看是局部的還是全局的還是堆的。如果是局部的就不能返回。如果是全局的就沒有關系了,如果是堆的那麼請記住要記得釋放掉。

三:方法

那麼對於一個函數來說,我該怎麼返回一個字符串呢。

方法如下:

方法一:返回一個指向字符串指針的常量。

char *func{return "only works for simple strings"}


http://www.linuxidc.com/Linux/2014-07/104737.htm 參見這篇博文,常量是存放再代碼段的,整個程序的執行周期都在不會因為子函數的結束而釋放。

這是最簡單的解決方案,但是如果你需要對字符串處理那就無能為力了。

方法二:使用全局數組

char *func(){

    my_global_array[i] = 'a';

    return my_global_array;

}


這種方法也是很簡單易用的,但是大量創建這樣的全局字符串數組增加了程序的耦合性。並且任何人都可以修改這個全局數組,而且下一次函數調用也會覆蓋該數組的內容。

方法三:使用靜態數組

char * func(){

    static char buffer[20];

    return buffer;

}

http://www.linuxidc.com/Linux/2014-07/104737.htm  參見這篇博文,靜態變量是存放在數據段的也是整個程序執行周期都不釋放的。

這種方法比使用全局數組要好,可以防止任何人修改這個數組的內容,只有擁有該數組的指針函數才能修改這個靜態數組。但是函數下一次調用將覆蓋這個數組的內容。

方法四:顯示分配一些內存

char *func()

{

    char *s = malloc(120);

    return s;

}

http://www.linuxidc.com/Linux/2014-07/104737.htm 參見這篇博文mlloc分配的內存是放在堆段的,只有編程者自己手動通過free來釋放內存的。所以不會因為函數執行完畢就釋放其內存。

但是這種方法要求編程者謹記要自己手動釋放內存,這種寫法不太好,因為malloc和free不在同一個代碼塊中很容易忘記使用free.

方法五:也許是最好的解決方案

void func(char *result,int size)

{

    strcpy(result,"test",size);

}

buffer = malloc(size);

func(buffer,size);

free(buffer);

這種方案只要malloc和free的使用在一個代碼塊中那麼內存管理就顯得輕松了。

四:總結

C語言真的很簡單,簡單到什麼都要自己做。

Copyright © Linux教程網 All Rights Reserved