关于函数返回值为指针类型的分析

先看一个例子,这是初学者经常遇到的问题

char*GetString(void)
{
 char p[]= "hello world";
 return p;
//编译器一般将提出警告信息

}
void main(void)
{
 char *str = NULL;
 str = GetString();
//str 的内容是垃圾,得不到想要的内容

 count<< str<<end;
}

在函数GetString()中定义的变量p属于local(局部变量),当函数结束时自动消失,所以在返回时,根本就 得不到P所指的内容。解决办法有以下几种:(可能还有很多方法,不过这里只是最常见的几中,也是最能体 表现程序中内存使用的情况。)
(1)可以使用全局数组。使用全局变量时,在程序结束时才释放。
(2)在函数GetString()中使用new在堆上动态分配内存来建立数组。C语言中可以使用malloc()函数。不过不
要忘记了,在使用完后要进行内存的释放,不然会造成内存的泄漏。分别用delete,free(),释放。使用delete 时,会调用类的析构函数,而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

  }

(3)可以定义为静态类型,static char p[]="hello world"。用static   声明一个指针可以,但也不太好,
因为如果你多次调用这个函数返回多个指针,但这几个指针实际上指向同一块地址,改变任何一个的内容将改变 所有指针的内容, 这样也不是很多情况所需要的。

char* GetString(void)
  {
          static char p[]="hello world";
          return p;
//p为静态创建,程序退出时才释放

  } 

(4)用String类型,用string   实现,是值拷贝!不存在释放内存会影响拷贝的问题。

string GetString(void)
  {
            char p[]= "hello world";
            return p;
  }
  void Test4(void)
  {
            string str;
            str = GetString();
            cout<< str.c_str()<< endl;
  }


(5)使用字符串常量,因为字符串常量存储再静态存储区域,所以一直都存在,p是临时变量,但过程结束并不 会释放这个字符串常量.而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);
            cout<< str<< endl;
  }


一般在函数中定义一个对象有两种方法:  
  1、在栈上建立局部变量。注意,在栈上时!栈用于函数是为了返回时找得到调用点(在调用时压入栈的)
,那么,返回时要POP才能得到。函数体中建立的任何东西都消失了(返回值除外),你返回的指针指向的内
容现在不知被用作什么用途了,如果你还要修改的话,那么后果不能确定。  

  2、在堆中分配。返回时不会摧毁,因为堆是全局存在的。但函数的调用者要记得delete回来的指针。


看以下程序:
==========================================================================
char* GetFileName()
{
char filename[] = “file_0001.dat”;
strcpy(filename,"file_xxxx");
return filename;
}
void main()
{
char* s;
s = GetFileName();
printf(“%s\n”, s);
}
=============================================================================
编译程序出错,提示为:
warning C4172: returning address of local variable or temporary
意思就是说,不能试图把局部变量的指针作为函数的返回值。
为什么?
        函数作为独立的模块,在其内部声明和使用的变量都是局部变量,他们都是存在栈上的,当函数调用完成时,会清理掉这些局部变量,这样在调用完函数后再企图通过返回的局部变量指针得到局部变量是非法的。
        但是,有个例外情况,就是在C语言中使用malloc函数分配的指针变量是在堆上动态分配的,它不受函数生命周期的影响,因此在函数调用并结束后,使用malloc分配的指针仍然有效。对于C++中的new操作符,同样因为是在堆上面分配内存,不会丢掉,可以在函数调用结束后继续访问。
        注意,因为使用了malloc函数或new操作符,在程序结束前,我们就要显示地使用free函数或者delete指令销毁之前分配的堆变量指针。

例:
void* getData(ATTR attribute)
{
    int i;
    uchar* singleUbyte = NULL;
    ushort* singleUint16 = NULL;
    ulong* singleUint32 = NULL;
    short* singleSint16 = NULL;
    long* singleSint32 = NULL;
    real* singleReal32 = NULL;
    VALUE * vData = NULL;

    PositionUByte* posUByte = NULL;
    PositionUShort* posUShort = NULL;
    PositionULong* posULong = NULL;
    PositionShort* posShort = NULL;
    PositionLong* posLong = NULL;
    PositionFloat* posFloat = NULL;
    
    BoxUByte* boxUByte = NULL;
    BoxUShort* boxUShort = NULL;
    BoxULong* boxULong = NULL;
    BoxShort* boxShort = NULL;
    BoxLong* boxLong = NULL;
    BoxReal* boxReal = NULL;
    

    if(attribute.data.param.type == Single)
        switch (attribute.data.param.size)
        {
        case Ubyte:
            singleUbyte = (uchar*)malloc(sizeof(uchar));
            *singleUbyte = attribute.data.param.t.s.ubyte;
            return singleUbyte;
        case Uint16:
            singleUint16 = (ushort*)malloc(sizeof(ushort));
            *singleUint16 = attribute.data.param.t.s.uint16;
            return singleUint16;
        case Uint32:
            singleUint32 = (ulong*)malloc(sizeof(ulong));
            *singleUint32 = attribute.data.param.t.s.uint32;
            return singleUint32;
        case Sint16:
            singleSint16 = (short*)malloc(sizeof(short));
            *singleSint16 = attribute.data.param.t.s.sint16;
            return singleSint16;
        case Sint32:
            singleSint32 = (long*)malloc(sizeof(long));
            *singleSint32 = attribute.data.param.t.s.sint32;
            return singleSint32;
        case Real32:
            singleReal32 = (real*)malloc(sizeof(real));
            *singleReal32 = attribute.data.param.t.s.real32;
            return singleReal32;
        default:
            break;
        }
    if(attribute.data.param.type == Xy)
        switch (attribute.data.param.size)
        {
        case Ubyte:
            posUByte = (PositionUByte*)malloc(sizeof(PositionUByte));
            posUByte->x = attribute.data.param.t.xy.v1.ubyte;
            posUByte->y = attribute.data.param.t.xy.v2.ubyte;
            return posUByte;
        case Uint16:
            posUShort = (PositionUShort*)malloc(sizeof(PositionUShort));
            posUShort->x = attribute.data.param.t.xy.v1.uint16;
            posUShort->y = attribute.data.param.t.xy.v2.uint16;
            return posUShort;
        case Uint32:
            posULong = (PositionULong*)malloc(sizeof(PositionULong));
            posULong->x = attribute.data.param.t.xy.v1.uint32;
            posULong->y = attribute.data.param.t.xy.v2.uint32;
            return posULong;
        case Sint16:
            posShort = (PositionShort*)malloc(sizeof(PositionShort));
            posShort->x = attribute.data.param.t.xy.v1.sint16;
            posShort->y = attribute.data.param.t.xy.v2.sint16;
            return posShort;
        case Sint32:
            posLong = (PositionLong*)malloc(sizeof(PositionLong));
            posLong->x = attribute.data.param.t.xy.v1.sint32;
            posLong->y = attribute.data.param.t.xy.v2.sint32;
            return posLong;
        case Real32:
            posFloat = (PositionFloat*)malloc(sizeof(PositionFloat));
            posFloat->x = attribute.data.param.t.xy.v1.real32;
            posFloat->y = attribute.data.param.t.xy.v2.real32;
            return posFloat;
        default:
            break;
        }
    if(attribute.data.param.type == Box)
        switch (attribute.data.param.size)
        {
        case Ubyte:
            boxUByte = (BoxUByte*)malloc(sizeof(BoxUByte));
            boxUByte->left = attribute.data.param.t.b.v1.ubyte;
            boxUByte->top = attribute.data.param.t.b.v2.ubyte;
            boxUByte->right = attribute.data.param.t.b.v3.ubyte;
            boxUByte->bottom = attribute.data.param.t.b.v4.ubyte;
            return boxUByte;
        case Uint16:
            boxUShort = (BoxUShort*)malloc(sizeof(BoxUShort));
            boxUShort->left = attribute.data.param.t.b.v1.uint16;
            boxUShort->top = attribute.data.param.t.b.v2.uint16;
            boxUShort->right = attribute.data.param.t.b.v3.uint16;
            boxUShort->bottom = attribute.data.param.t.b.v4.uint16;
            return boxUShort;
        case Uint32:
            boxULong = (BoxULong*)malloc(sizeof(BoxULong));
            boxULong->left = attribute.data.param.t.b.v1.uint32;
            boxULong->top = attribute.data.param.t.b.v2.uint32;
            boxULong->right = attribute.data.param.t.b.v3.uint32;
            boxULong->bottom = attribute.data.param.t.b.v4.uint32;
            return boxULong;
        case Sint16:
            boxShort = (BoxShort*)malloc(sizeof(BoxShort));
            boxShort->left = attribute.data.param.t.b.v1.sint16;
            boxShort->top = attribute.data.param.t.b.v2.sint16;
            boxShort->right = attribute.data.param.t.b.v3.sint16;
            boxShort->bottom = attribute.data.param.t.b.v4.sint16;
            return boxShort;
        case Sint32:
            boxLong = (BoxLong*)malloc(sizeof(BoxLong));
            boxLong->left = attribute.data.param.t.b.v1.sint32;
            boxLong->top = attribute.data.param.t.b.v2.sint32;
            boxLong->right = attribute.data.param.t.b.v3.sint32;
            boxLong->bottom = attribute.data.param.t.b.v4.sint32;
            return boxLong;
        case Real32:
            boxReal = (BoxReal*)malloc(sizeof(BoxReal));
            boxReal->left = attribute.data.param.t.b.v1.real32;
            boxReal->top = attribute.data.param.t.b.v2.real32;
            boxReal->right = attribute.data.param.t.b.v3.real32;
            boxReal->bottom = attribute.data.param.t.b.v4.real32;
            return boxReal;
        default:
            break;
        }
    if(attribute.data.param.type == Array)
        vData = attribute.data.param.t.a.valp;
        switch (attribute.data.param.size)
        {
            case Ubyte:
                singleUbyte = (uchar*)malloc(attribute.data.param.t.a.len*sizeof(uchar));
                for(i = 0;i < attribute.data.param.t.a.len;i++)
                {
                    singleUbyte[i] = (*vData).ubyte;
                    vData++;
                }
                return singleUbyte;
            case Uint16:
                singleUint16 = (ushort*)malloc(attribute.data.param.t.a.len*sizeof(ushort));
                for(i = 0;i < attribute.data.param.t.a.len;i++)
                {
                    singleUint16[i] = (*vData).uint16;
                    vData++;
                }
                return singleUint16;
            case Uint32:
                singleUint32 = (ulong*)malloc(attribute.data.param.t.a.len*sizeof(ulong));
                for(i = 0;i < attribute.data.param.t.a.len;i++)
                {
                    singleUint32[i] = (*vData).uint32;
                    vData++;
                }
                return singleUint32;
            case Sint16:
                singleSint16 = (short*)malloc(attribute.data.param.t.a.len*sizeof(short));
                for(i = 0;i < attribute.data.param.t.a.len;i++)
                {
                    singleSint16[i] = (*vData).sint16;
                    vData++;
                }
                return singleSint16;
            case Sint32:
                singleSint32 = (long*)malloc(attribute.data.param.t.a.len*sizeof(long));
                for(i = 0;i < attribute.data.param.t.a.len;i++)
                {
                    singleSint32[i] = (*vData).sint32;
                    vData++;
                }
                return singleSint32;
            case Real32:
                singleReal32 = (float*)malloc(attribute.data.param.t.a.len*sizeof(float));
                for(i = 0;i < attribute.data.param.t.a.len;i++)
                {
                    singleReal32[i] = (*vData).real32;
                    vData++;
                }
                return singleReal32;
            default:
                break;
        }

    return NULL;
}

  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值