[C语言]返回指针的函数

定义 : 类型名 *函数名(函数参数表列);
int *compare(float a,float b);

一个我们最最常见的老师说的错误例子

char*GetString(void)
{
 char p[]= "hello world";
 return p; //编译器一般将提出警告信息
}
void main(void)
{
 char *str = NULL;
 str = GetString();//str 的内容是垃圾,得不到想要的内容
 printf("%s\n",str);
}

在函数 GetString() 中定义的变量 p 属于 local (局部变量),当函数结束时自动消失,所以在返回时,根本就得不到 p 所指的内容。

那么什么时候可以返回函数内变量的地址且地址所指向的内容是我们所需要的呢?

我们都知道指针函数的返回指针不能指向函数内的自动变量,如果需要返回函数的内部变量的话,就需要要求该 变量的地址指向的内存 在函数结束后不被释放(变量可以被释放,不影响);
这时候,我们就需要了解程序的存储区域的问题了
(本人参考了:函数能否返回函数内指针 link.)
大概分为一下五种情况:

  1. 使用全局变量。使用全局变量时,在程序结束时才释放。
  2. 在函数中动态分配内存。动态分配的内存只有在调用 free(); 内存空间后才被释放。
char*GetString()
  { 
  char *p;
  p = (char*)malloc(100);
  return p;
  }    
  void main()
  { 
  char *str=NULL;  
  str=GetString();
  strcpy(str,"Hello");
  printf("%s", str);
  free(str);//free memroy
  }
  1. 定义为静态类型,static char p[]=“hello world”;
char* GetString(void)
  { 
          static char p[]="hello world";
          return p;//p为静态创建,程序退出时才释放
  } 
  1. 用String类型,用string 实现,是值拷贝!不存在释放内存会影响拷贝的问题。
string GetString(void)
  { 
            char p[]= "hello world";
            return p;
  } 
  void Test4(void)
  { 
            string str;
            str = GetString();
            printf("%s", str);
  } 
  1. 使用字符串常量,因为字符串常量存储再静态存储区域,所以一直都存在。
    例如对于字符串指针变量: char *p = “China”;
    其中 p 是临时变量,"China"是字符串常量,函数结束 p 被释放,但字符串常量"China"并不会被释放。
    但对于数组:char p[ ] = “China”;
    就不一样了,p[ ] 是一个数组,数组里面存放了字符串,这个字符串没有放在字符串常量,而是存储在静态存储区域,p 是临时变量,跳出函数之后,一般保留一步就释放了,数组的空间回收了,字符串没有了。
constchar *GetString(void)
  { 
            const char *p ="hello world";
            return p;
  } 
  char *GetString(void)
  { 
            char *p= "hello world";
            return p;
  } 
 void GetString(char* p)
  { 
            strcpy(p,"hello world");
  } 
  void Test4(void)
  { 
            char str[100];
            GetString(str);
            printf("%s", str);
  }

[ 以上五点主要参考和引用于:
关于函数返回值为指针类型的分析 link.]
此外,特别注意一个易混淆的例子


#include <stdio.h>  //头文件  
#include <stdlib.h> 
 
char *cmonth(int month);//函数声明  
 
int main()  
{  
    int i;  
 
    printf("输入月份数字:");  
    scanf("%d",&i); //输入月份  
    printf("月份:%2d-->英文名称:%s\n",i,cmonth(i));  
 
    system("pause");  
    return 0;  
}  
 
char *cmonth(int month)//自定义函数  
{  
    char *str_month[]={//初始化  
                    "Illegal Month",  
                    "January",  
                    "February",  
                    "March",  
                    "April",  
                    "May",  
                    "June",  
                    "July",  
                    "August",  
                    "September",  
                    "October",  
                    "November",  
                    "December"  
                   };  
    char *p;  
 
    if(month>=1 && month<=12)       //判断是否合法  
        p=str_month[month];  
    else  
        p=str_month[0];  
    return p;  
} 

[ 例子的代码来源于:starive_giant
原文:返回指针的函数link.]
该例子本人乍一看觉得不对劲 str_month[ ] 是一个字符串数组,但仔细瞧可以看出 * str_month[ ]是一个指针数组,数组里面的每一个元素都是一枚指针,指针指向的字符串是存储在字符串常量里的,因此该例子没问题。
若将 *str_month[ ]改为str_month [12] [ ]则经行运行,会出现错误……(此处主要涉及的是第五点知识点)

总结一下

编写指针函数使要注意返回值。
总体原则是:返回的指针对应的内存空间不会因函数返回则被释放掉。
常用的返回指针有以下几种:

  • 函数中动态分配内存空间(通过malloc等实现)的首地址;
  • 静态变量(static)或全局变量所对应的变量的首地址;
  • 通过指针形参所获得的实参的有效地址。
本文参考和照搬了一些文章,但本人粗略一瞧,应该都带上了原文链接,若有处理不妥之处或文章有错误,缺陷,可以补充之处,望大家之处,本人即当改正完善和感谢!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值