詳解C語(yǔ)言函數(shù)返回值解析
詳解C語(yǔ)言函數(shù)返回值解析
程序一:
int main()
{
  int *p;
  int i;
  int*fun(void);
  p=fun();
  for(i=0;i<3;i++)
  {
    printf("%d\n",*p);
    p++;  
  }
  return 0;
};
int* fun(void)
{
  static int str[]={1,2,3,4,5};
   int*q=str;
  return q;
}
//不能正確返回
雖然str是在動(dòng)態(tài)變量區(qū),而該動(dòng)態(tài)變量是局部的,函數(shù)結(jié)束時(shí)不保留的。
程序二:
int main()
{
  char *p;
  char*fun(void);
  p=fun();
  printf("%s\n",p);
  return 0;
};
char * fun(void)
{
  char *str="hello";
  return str;
}
//可以正確返回
但是,字符串"hello"不是變量,而是一個(gè)常量,編譯程序在處理這種常量時(shí),通常把它放在了常量區(qū)中。而常量區(qū)則是始終存在的。
后一個(gè)例子中函數(shù)fun的返回值就是一個(gè)指向這種常量區(qū)的指針。
函數(shù)返回指針,要使主程序可以使用這個(gè)指針來(lái)訪問(wèn)有意義的數(shù)據(jù),關(guān)鍵就是要保證在使用這個(gè)指針值的時(shí)候,該指針?biāo)赶虻牡胤降臄?shù)據(jù)仍然有意義。
還有,如果指針是指向函數(shù)的指針,那么這個(gè)指針就是指向程序代碼區(qū)的。這也是一種應(yīng)用的情況。
另外,如果明白了它的原理,程序員還可以發(fā)明出一些其他靈活的使用方法,當(dāng)然,那都屬于“怪”方法,一般不提倡的。
程序三:
int main()
{
  int a,b;
  int max;
  int fun (int a,int b);
  scanf("%d%d",&a,&b);
  max=fun (a,b);
  printf("\n%d\n",max);
  return 0;
};
//http://www.bianceng.cn
int fun(int a,int b)
{
  int max;
  if(a>b)
    max=a;
  else
    max=b;
  return max;
}
//可以正確返回
程序三:
這個(gè)例子中,返回的不是變量max的地址,返回的是它的值。
return后面的東西,看做一個(gè)表達(dá)式,返回的是這個(gè)表達(dá)式的值。
例如,入口如果a是3,b是5,則此時(shí)(執(zhí)行return語(yǔ)句時(shí))max里面存的是5。而return語(yǔ)句的功能就是把max里面的5取出來(lái),放到“返回值寄存器”中。
主程序是從“返回值寄存器”得到這個(gè)5的(此時(shí)max變量已經(jīng)不存在了)。
你前面的第二個(gè)例子中,同樣,指針變量str在函數(shù)結(jié)束后已經(jīng)不存在了。但是在return語(yǔ)句中,把指針變量str里面的值(等于字符串"hello"存放處的地址)送到“返回值寄存器”中了。
動(dòng)態(tài)變量str不存在了,但常量區(qū)中的字符串"hello"還存在。主程序根據(jù)返回的地址就可以找到該字符串。
程序四:
int main()
{
  char *p;
  char *fun(void);
  p=fun();
  printf("%x\n",p);
  printf("%s\n",p);
  return 0;
}
char* fun(void)
{
//  char str[]={'a','b','c','d','e','f','\0'};
  char str[]="hello";
  printf("%x\n",str);
  return str;
}
//不能正確返回
char str[]="hello"; 是在動(dòng)態(tài)變量區(qū)中開(kāi)辟了可以容納6個(gè)字符的數(shù)組,數(shù)組名叫str。同時(shí)將字符串"hello"(原存放于常數(shù)空間)拷貝到這個(gè)數(shù)組空間中去作為數(shù)組的初始化值。
此時(shí)若執(zhí)行return str; 其中的str是數(shù)組名。C語(yǔ)言規(guī)定,表達(dá)式中如果是數(shù)組名,則該表達(dá)式的值就等于這個(gè)數(shù)組的地址。所以返回的是這個(gè)數(shù)組的地址,請(qǐng)注意:并不是字符串常量"hello"的地址!而函數(shù)結(jié)束時(shí),雖然常數(shù)空間并不破壞,但這個(gè)數(shù)組空間是破壞了的,而你返回的卻不是常數(shù)空間里的地址而正是已經(jīng)破壞了的數(shù)組的地址。
而char *str="hello"; 是在動(dòng)態(tài)變量區(qū)中開(kāi)辟了一個(gè)可以存放一個(gè)指針值的變量,名叫str。同時(shí)將原存放于常數(shù)空間的字符串"hello"的地址賦給這個(gè)指針變量作為初始值。
此時(shí)若執(zhí)行return str; 其中的str是指針變量名。C語(yǔ)言規(guī)定,表達(dá)式中如果是變量名,則該表達(dá)式的值就等于這個(gè)變量的值(指針變量的值就是地址)。所以返回的是變量str的值,而變量str的值就等于字符串常量"hello"的地址。而函數(shù)結(jié)束時(shí),變量str破壞了的,但常數(shù)空間中的字符串并不破壞。主程序根據(jù)返回的地址就可以找到該字符串。
【總結(jié)】
常規(guī)程序中,函數(shù)返回的指針通常應(yīng)該是:
(1)指向靜態(tài)(static)變量;
(2)指向?qū)iT申請(qǐng)分配的(如用malloc)空間;
(3)指向常量區(qū)(如指向字符串"hello");
(4)指向全局變量;
(5)指向程序代碼區(qū)(如指向函數(shù)的指針)。
除這5項(xiàng)以外,其它怪技巧不提倡。
函數(shù)內(nèi)的變量,沒(méi)有關(guān)鍵字static修飾的變量的生命周期只在本函數(shù)內(nèi),函數(shù)結(jié)束后變量自動(dòng)銷毀。當(dāng)返回為指針的時(shí)候需要特別注意,因?yàn)楹瘮?shù)結(jié)束后指針?biāo)赶虻牡刂芬廊淮嬖冢窃摰刂房梢员黄渌绦蛐薷?,里面的?nèi)容就不確定了,有可能后面的操作會(huì)繼續(xù)用到這塊地址,有可能不會(huì)用到,所以會(huì)出現(xiàn)時(shí)對(duì)時(shí)錯(cuò)的情況,如果需要返回一個(gè)指針而又不出錯(cuò)的話只能調(diào)用內(nèi)存申請(qǐng)函數(shù)
返回結(jié)構(gòu)體:
#include <stdio.h>
typedef struct {
      int a;
      int b;
      int c;
    }str;
str change(str s)
{
  s.a += 1;
  s.b += 1;
  s.c += 1;
  return s;
}
int main(void)
{
  str s1, s2;
  s1.a = 1;
  s1.b = 1;
  s1.c = 1;
  s2 = change(s1);
  printf("s1.a = %d\ts1.b = %d\ts1.c = %d\n",s1.a, s1.b, s1.c);
  printf("s2.a = %d\ts2.b = %d\ts2.c = %d\n",s2.a, s2.b, s2.c);
  return 0;
}
//可以返回
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
上一篇:數(shù)據(jù)結(jié)構(gòu)用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的實(shí)例
欄 目:C語(yǔ)言
下一篇:C語(yǔ)言中雙向鏈表和雙向循環(huán)鏈表詳解
本文標(biāo)題:詳解C語(yǔ)言函數(shù)返回值解析
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/1443.html
您可能感興趣的文章
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用函數(shù)刪除字符
 - 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)式函數(shù)庫(kù)
 - 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
 - 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
 - 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段函數(shù)
 - 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排序法函數(shù)
 - 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
 - 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段函數(shù)
 - 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎么打出三角函數(shù)的值
 - 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求階乘
 


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
 - 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
 - 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
 - 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
 - 5c語(yǔ)言計(jì)算三角形面積代碼
 - 6什么是 WSH(腳本宿主)的詳細(xì)解釋
 - 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
 - 8正則表達(dá)式匹配各種特殊字符
 - 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
 - 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
 
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
 - 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
 - 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
 - 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
 - 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
 - 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
 - 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
 - 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
 - 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
 - 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
 
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
 - 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
 - 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
 - 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
 - 01-10C#中split用法實(shí)例總結(jié)
 - 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
 - 04-02jquery與jsp,用jquery
 - 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
 - 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
 - 01-10delphi制作wav文件的方法
 


