您的位置:首页 > 其它

返回static的变量指针危险和printf的执行顺序

2012-03-16 09:47 337 查看
char* fun(const char* src)
{
static char dest[32] = "";

strcpy(dest, src);

return dest;
}

int main(int argc, char* argv[])
{
char s1[32] = "";
char s2[32] = "";

strcpy(s1, fun("hello"));
strcpy(s2, fun("world"));

printf("%s %s\n", s1, s2);
printf("%s %s\n", fun("hello"), fun("world"));

getchar();
}


上文在vs2008的执行结果如下

hello world

hello hello

从以上结果可以看出

1.printf函数从右执行

2.返回static变量的指针有点危险。值则不会有这个问题。

上面的这段代码确实不能看,字符串复制,不需要传入长度参数,也不根据结束符判断大小,也无法确定是否会溢出。不可取,不可取。

我们在写C/C++程序的时候,经常需要从调用函数中取得自己想要的数据,这就需要调用者和函数之间要有个内存的交互,我们通常采用的方法是传递一个指针给被调函数,作为被调函数的输出参数,这也是我们常用的、规范的做法。

但有很多程序员比较习惯直接取返回值,这就面临一个问题就是普通局部变量都是在栈上分派的,会随着函数的结束而弹栈释放,那么就会出现返回局部变量数组的问题,这时有人会想到用malloc或new在堆上分派内存,没错,这样是避免了前面说的问题,但这样又会带来新的问题,就是需要在外部对这块内存进行释放,这个是比较难把握的,多次释放会出现程序的crash,忘记释放了会出现内存leak,所以这种方法也不被推荐。还有人想到了更另类的方法,就是上面例子中的static类型,没错,static变量也是全局的,但就会出现上面程序的运行结果(可以认为不是我们想要的结果,也就是错误的结果)。

所以,我们要慎用返回函数内部的static内存的这种设计,但如果在无法改变设计模式的情况下(有些系统函数的实现,比如inet_ntoa,可以通过在man手册中看到这样的一句话:The string is returned in a statically allocated buffer,
which subsequent calls will overwrite),那么在自己使用的时候一定要注意,不要试图保存返回的内存地址或引用,而要保存返回内存的内容,也就是例子程序中的strcpy两行。

inet_ntoa的错误使用(判断两个IP地址是否相等):

1

struct in_addr addr1;

2

struct in_addr addr2;

3


4

// 网络包中包含了源地址

5

addr1.s_addr = 0x6500A8C0 // 192.168.0.101

6

addr2.s_addr = 0x6600A8C0 // 192.168.0.102

7


8

// 这个if语句将永远为真

9

if (strcmp(inet_ntoa(addr1), inet_ntoa(addr2)) == 0) {

10

// do something

11

} else {

12

// do other thing

13

}

看官笑过,出差回来水一篇
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐