精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>C、C++语言基础>>关于返回指针的讨论

主题:关于返回指针的讨论
发信人: ken_qian()
整理人: wenbobo(2002-12-06 22:08:55), 站内信件
初始化:虽然教科书上经常讲初始化、初始化,但我经常
只在定义指针的时候将它初始化为NULL,这样的习惯很
不好,但也不为什么就一直没有改,也许因为习惯使然吧。

不要将堆栈里的指针返回,我犯过如下错误:
char * int2str(int i){
    char str[20];
    sprintf("%d",i);
    return str;
}
我这么作,错误的原因就在于,编译器通常会在堆栈里分
配临时的存储空间给str这样的局部变量。当局部变量的作
用结束以后,编译器经常擅自将其挪作它用。我没有得到
我想要的,和应得的。那么,你实在想要str的地址的话,
传统作法是将str定义为static,那么编译器就会为其永久的
分配一块自留地。但是str将受严密的控制,其它函数不可
能直接访问str,虽然它始终存在。
好的解决方法是用缓冲区:
char * int2str(int i,char * pBuffer,int nBufferSize){
    ....
    return pBuffer;
}
最好指明缓冲的大小,以便函数可以检测缓冲是否足够。

给字符串分配内存时,不要忘了最后的'\x0',C不提供数
组的边界检测,它相信你自己能作到这一点。那么不要
忘记留给字符串数组多留一个结束的标志。(我常犯的毛病)

Ken

10:42

--
杀意隆目中神光咋现,一向清澄的眼眸中竟闪现出三分歹毒,四分杀意。

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.9.248]
发信人: crazyjava (骄傲的中国人), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Tue Jun 29 14:11:35 1999), 站内信件

【 在 ken_qian (<marquee>杀意隆) 的大作中提到: 】
: 初始化:虽然教科书上经常讲初始化、初始化,但我经常
: 只在定义指针的时候将它初始化为NULL,这样的习惯很
: 不好,但也不为什么就一直没有改,也许因为习惯使然吧。

:    .......

这也是我初学时常犯的错误,不过现在不会了。
你那种是其中一个流行的作法,而我习惯尽量减少
input parameters,所以以下是我的做法:

char * int2str(int i)

   char str[20]; 
   ::sprintf( str, "%d",i); 

   char *pBuffer = new char[ ::strlen( str ) + 1 ];
   ::strcpy( pBuffer, str );
   return pBuffer; 


若担心size of buffer是20太小,可以自己控制:

char * int2str( int i, int iBufferSize = 20 )

   char *pStr = new char[ iBufferSize + 1 ]; 
   ::sprintf( pStr, "%d",i); 

   char *pBuffer = new char[ ::strlen( pStr ) + 1 ];
   ::strcpy( pBuffer, pStr );
   delete []pStr;
   return pBuffer; 


这样一来,自己就不用操心string的初始化等问题了,
而且也可以节省memory,因为若i=1,而buffer的size是20
的话就浪费了19个bytes.我让它在function内重新分配多
一次,就决定了实际需要的字节数。

请指正, thanks.

--
孤身走我路...
其实,路,两个人一起走比一个人要好。
email: [email protected]

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.222]
发信人: ken_qian (<marquee>杀意隆), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Tue Jun 29 16:05:03 1999), 站内信件

我想说的是三件事
第一:变量申明时保持初始化的习惯。
第二:别把在函数里的局部变量指针作为返回值。
第三:再处理字符串数组时别忘了为'\x0'留个位置

Ken
16:59

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.9.248]
发信人: literfer (老温), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Tue Jun 29 16:27:27 1999), 站内信件

【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: 【 在 ken_qian (<marquee>杀意隆) 的大作中提到: 】
: : 初始化:虽然教科书上经常讲初始化、初始化,但我经常
: : 只在定义指针的时候将它初始化为NULL,这样的习惯很
: : 不好,但也不为什么就一直没有改,也许因为习惯使然吧。
:    .......

crazyjava兄的方法好是好,可是在使用了你的pBuffer后还得用delete删除,也
很烦的,是不是?

--
任我独行

发信人: crazyjava (骄傲的中国人), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Tue Jun 29 16:45:35 1999), 站内信件

【 在 literfer (老温) 的大作中提到: 】
: 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: : 【 在 ken_qian (<marquee>杀意隆) 的大作中提到: 】
: :    .......

:    .......

我方法的使用例子:
int i = 100;
int iBufferSize = 10;
char *p = int2str( i, iBufferSize );
...
delete [] p;

ken方法的使用例子:
int i = 100;
int iBufferSize = 10;
char *p = new char[ iBufferSize + 1 ];
int2str( i, p, iBufferSize );
...
delete [] p;

不过对于指针变量,一般使用完后,都要delete.
难道你有更好的方法?

我想假如想要自动处理的话,只好笨一点,用
class. :P

class A
{
    char *m_pBuffer;
  public:
    A() { m_pBuffer = NULL; }
    ~A() { if( m_pBuffer ) delete []m_pBuffer; }

    char * int2str( int i, int iBufferSize = 20 );
};

char* A::int2str( int i, int iBufferSize ) 
{  
    char *pStr = new char[ iBufferSize + 1 ];  
    ::sprintf( pStr, "%d",i);  

    if( m_pBuffer ) delete []m_pBuffer;
    m_pBuffer = new char[ ::strlen( pStr ) + 1 ]; 
    ::strcpy( m_pBuffer, pStr ); 
    delete []pStr; 
    return m_pBuffer;  
}  

example:
int i = 100;
A a;
char *p = a.int2str( i );
...

是不是有点小题大作 :P


--
孤身走我路...
其实,路,两个人一起走比一个人要好。
email: [email protected]

※ 修改:.crazyjava 于 Jun 29 16:47:53 修改本文.[FROM: 139.87.93.222]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.222]
发信人: vcc (vcc), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Tue Jun 29 18:29:47 1999), 站内信件

【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: 【 在 literfer (老温) 的大作中提到: 】
: : 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: : 
: :    .......
:    .......
想要偷懒还是有办法的^-^
const char* int2str(int i) {
static char buf[20];
return(_itoa(i,buf,10));
}

--
世事风云多变换
  程序依然在我心

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.146.7]
发信人: YW (老GUN), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易 BBS (Tue Jun 29 20:55:38 1999), 转信

绝对不可以把str定义为static, 否则如下调用就会出现错误:

  a= int2str(100);
  b= int2str(200); //执行这句时同时把a的值也改成了"200"!!


【 在 ken_qian (<marquee>杀意隆) 的大作中提到: 】
: 初始化:虽然教科书上经常讲初始化、初始化,但我经常
: 只在定义指针的时候将它初始化为NULL,这样的习惯很

--
※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.137.27]
发信人: ken_qian (<marquee>杀意隆), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Wed Jun 30 08:03:13 1999), 站内信件

【 在 YW (老GUN) 的大作中提到: 】
: 绝对不可以把str定义为static, 否则如下调用就会出现错误:
:   a= int2str(100);
:   b= int2str(200); //执行这句时同时把a的值也改成了"200"!!
: 【 在 ken_qian (<marquee>杀意隆) 的大作中提到: 】
:    .......

a等于200是正常结果,我想我已经写得很清楚了,你用static分配的
是永久的内存(你的程序运行的时候),如果a的指向那块内存,那么
内存的内容变了,*a也变了正是正常的情况,不变我才觉得有些奇
怪。
我想我举这个例子,只是想告诉大家,不要把堆栈里的指针返回,
那是错的。

Ken

8:57

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.9.248]
发信人: jaygee (jaygee), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到呢?
发信站: 网易虚拟社区 (Wed Jun 30 10:24:38 1999), 站内信件

【 在 ken_qian (<marquee>杀意隆) 的大作中提到: 】
: 初始化:虽然教科书上经常讲初始化、初始化,但我经常
: 只在定义指针的时候将它初始化为NULL,这样的习惯很
: 不好,但也不为什么就一直没有改,也许因为习惯使然吧。

:    .......

pbuffer已经是指针了,又何必再return呢?

--
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.24.6]
发信人: crazyjava (骄傲的中国人), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到
发信站: 网易虚拟社区 (Tue Jun 29 19:21:28 1999), 站内信件
【 在 vcc (vcc) 的大作中提到: 】
: 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: : 【 在 literfer (老温) 的大作中提到: 】
: :    .......
: 想要偷懒还是有办法的^-^
: const char* int2str(int i) { 
:   static char buf[20]; 
:    return(_itoa(i,buf,10)); 
: }
哈哈,我们讨论的主要是char*的使用。若用itoa
我的写法还是:
char * int2str(int i) 
{  
     char str[20];  
     _itoa(i,str,10); 
     char *pBuffer = new char[ ::strlen( str ) + 1 ]; 
     ::strcpy( pBuffer, str ); 
     return pBuffer;  
}  
原因也是一个save memory :)
--
孤身走我路...
其实,路,两个人一起走比一个人要好。
email: [email protected]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.222]
发信人: vcc (vcc), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到
发信站: 网易虚拟社区 (Wed Jun 30 10:15:59 1999), 站内信件
【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: 【 在 vcc (vcc) 的大作中提到: 】
: : 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: : 想要偷懒还是有办法的^-^
:const char* int2str(int i) {  
:    static char buf[20];  
    ^^^^^^^^
:     return(_itoa(i,buf,10));  
:  } 
看见static 没有?^-^
--
世事风云多变换
  程序依然在我心
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.146.7]
发信人: crazyjava (骄傲的中国人), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到
发信站: 网易虚拟社区 (Wed Jun 30 10:21:55 1999), 站内信件
【 在 vcc (vcc) 的大作中提到: 】
: 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: : 【 在 vcc (vcc) 的大作中提到: 】
: :const char* int2str(int i) {  
: :    static char buf[20];  
:    .......
: 看见static 没有?^-^
我个人不推荐使用static, 可免则免,因为浪费内存。
同时容易产生错误:
const char* a = int2str( 100 ); // a = "100"
const char* b = int2str( 200 ); // b = "200" 且 a = "200"
(YW已经在前面指出过了)
--
孤身走我路...
其实,路,两个人一起走比一个人要好。
email: [email protected]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.183]
发信人: YW (老GUN), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到
发信站: 网易 BBS (Wed Jun 30 10:53:07 1999), 转信
在函数内部使用辅助的全局变量首先碰到的一个问题就是该函数会
变成非线程安全的. 这意味着该函数将来在重用上会受到限制, 不小心
就会导致BUG的出现.
【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: 【 在 vcc (vcc) 的大作中提到: 】
: : 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
: :    .......
: : 看见static 没有?^-^

: 我个人不推荐使用static, 可免则免,因为浪费内存。
: 同时容易产生错误:
: const char* a = int2str( 100 ); // a = "100"
: const char* b = int2str( 200 ); // b = "200" 且 a = "200"

: (YW已经在前面指出过了)

--
※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.137.38]
发信人: vcc (vcc), 信区: C
标  题: Re: 我碰到过的错误,你有没有碰到
发信站: 网易虚拟社区 (Wed Jun 30 11:12:49 1999), 站内信件
【 在 YW (老GUN) 的大作中提到: 】
: 在函数内部使用辅助的全局变量首先碰到的一个问题就是该函数会
: 变成非线程安全的. 这意味着该函数将来在重用上会受到限制, 不小心
: 就会导致BUG的出现.
: 【 在 crazyjava (骄傲的中国人) 的大作中提到: 】
:    .......
我完全同意你们的看法,我也认为用到str最好strdup一个,编程不应该偷懒
当然,也可以考虑用CString,这样就没问题了:
CString int2str(int i){
char buf[20];
return(CString(_itoa(i,buf,10)));
}
--
世事风云多变换
  程序依然在我心
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.146.7]



[关闭][返回]