小问题请教

nizainade 2008-02-22 12:08:23
有下面一段测试代码:
char*pTest=NULL;
char* test()
{
std::string a="abc";
pTest=(char*)a.c_str();
// char*p="abc";
// pTest=p;

return pTest;
}
void main()
{
test();
assert(pTest!=NULL);
printf("%s",pTest);
}

程序输出乱码,但是 把
std::string a="abc";
pTest=(char*)a.c_str();
注释掉,把下面本来的注释去掉就能显示正常,请问为什么
...全文
346 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
kukumouse 2008-02-25
  • 打赏
  • 举报
回复
char*p="abc"; //字符串在编译时分配在静态区,退出test()后内容还在.
std::string a="abc";//因为string是一个类,它的操作符"="是将"abc"拷贝到一个堆空间里面保存,当test()退出后,a的空间被释放了,所以该值已经失去意义,不可靠了.
herman~~ 2008-02-23
  • 打赏
  • 举报
回复
栈作用域
skefer 2008-02-23
  • 打赏
  • 举报
回复
首先,
char*p="abc"; // "abc" 编译时常量区分配
所以能输出期望的结果,但是这样的设计本身有问题
因为test内的“abc”是常量字符串,位于静态存储区,
它在程序生命期内恒定不变。无论什么时候调用test(),
它返回的始终是同一个“只读”的内存块



程序输出乱码时
std::string a="abc";
pTest=(char*)a.c_str();
test函数执行结束后,函数内分配的string a="abc"内存释放,pTest成为成为野指针。
而这个时候pTest不是NULL ,pTest成为野指针是指它指向的内存是没用的,不是把pTest变成NULL所以
assert(pTest!=NULL) //并不能判别pTest是否为野指针
结果输出野指针指向的乱码。




wjlsmail 2008-02-23
  • 打赏
  • 举报
回复
只能这样解释:

char * pcStr = "abc"; // "abc" 编译时常量区分配
string str = "abc"; // "abc" 运行时栈上分配
Mnky 2008-02-22
  • 打赏
  • 举报
回复
To pengxn:
1、我认为是你理解错了;
2、如果你想批驳我的关于pTest=p的观点,至少也要用到这一句吧。。。
pengxn 2008-02-22
  • 打赏
  • 举报
回复
Mnky 理解错楼主的意思了.

楼主原话

std::string a="abc";
pTest=(char*)a.c_str();
注释掉,把下面本来的注释去掉就能显示正常,请问为什么

意思是楼主可以正常使用的代码是

char* test()
{
std::string a="abc";
pTest=(char*)a.c_str();
char*p="abc";
pTest=p;

return pTest;
}



==================

而且"你用pTest=p,那么pTest直接指向了"abc",不管test()作用于如何,都不会影响。" 这个说法也是错误的
测试了一下
char*pTest=NULL; 
char* test()
{
std::string a="abc";
pTest=a.c_str();
cout<<"pTest1 = "<<pTest<<endl;
return pTest;
}
int main()
{
test();
cout<<"1"<<endl;
if(pTest==NULL)
cout<<"2"<<endl;
assert(pTest!=NULL);
cout<<"pTest = "<<pTest<<endl;
}


结果为
$ SS
pTest1 = abc
1
pTest =
Mnky 2008-02-22
  • 打赏
  • 举报
回复
你用pTest=p,那么pTest直接指向了"abc",不管test()作用于如何,都不会影响。
但是pTest=(char*)a.c_str();的话,pTest是和a相关的,a出了test()就不存在了,所以pTest也就无效了。
pengxn 2008-02-22
  • 打赏
  • 举报
回复
string 这个类在析造的时候会释放空间,所以pTest的内容会为空.
pengxn 2008-02-22
  • 打赏
  • 举报
回复
std::string a="abc";
这个变量的作用域只在 test() 函数之中,是一个临时变量.而pTest指向这个临时变量,
printf("%s",pTest)的时候pTest已经变成一个野指针了.
业余的CODER 2008-02-22
  • 打赏
  • 举报
回复
char*pTest=NULL;
char* test()
{
std::string a="abc";
pTest=(char*)a.c_str();
// char*p="abc";
// pTest=p;
return pTest;
}
void main()
{
test();
//test函数执行结束后,函数内分配的string a="abc"内存释放,pTest成为野指针。 assert(pTest!=NULL);
printf("%s",pTest);
}

ssdx 2008-02-22
  • 打赏
  • 举报
回复
char *p = "abc" abc在常量区定义,编译时分配,运行时地址固定。

std::string p = "abc" 运行时,栈上分配,函数结束后,出栈,野指针。
wumuyishu 2008-02-22
  • 打赏
  • 举报
回复
不管注释不注释两种做法都是不对 都是野指针的问题
不注释后 输出正确只是 因为"abc",是一个常量字符串 编译器放的位置是内存中特定的区域,是确定的不会被改变
而string 里的是在栈上申请空间来放置的 函数结束后 空间被释放了
Mnky 2008-02-22
  • 打赏
  • 举报
回复
回会18楼,a确实释放了,只能说你运气不错,释放了,但是数值还没有被破坏。其实已经是非法的了,得到2也不能说明什么。
pengxn 2008-02-22
  • 打赏
  • 举报
回复
int *pTest=NULL;

void test()
{
int a=2;
pTest=&a;
}
void main()
{
test();
assert(pTest!=NULL);
std::cout <<(*pTest);
}
-----------
按楼上的代码我编译了下,执行结果输出为0.

关于空间释放的问题,我觉得应该还和编译器,环境有关系.

个人觉得:
不过还是觉得这样的写法本身就存在野指针的问题,不应该这样写,否则获得的结果也是不确定的
nizainade 2008-02-22
  • 打赏
  • 举报
回复
那如果更改一下:
int *pTest=NULL;

void test()
{
int a=2;
pTest=&a;
}
void main()
{
test();
assert(pTest!=NULL);
std::cout<<(*pTest);
}
上面,int a=2;a并不是常量,那为什么main中pTest也能输出2,在test中a的内存肯定释放了的啊
白乔 2008-02-22
  • 打赏
  • 举报
回复
可以这个理解吧

其实是:一个是直接赋值,一个是拷贝赋值
nizainade 2008-02-22
  • 打赏
  • 举报
回复
那是不是说,只有通过指针才能访问常量内存区域
nizainade 2008-02-22
  • 打赏
  • 举报
回复
那是不是说,只有指针通过指针才能访问常量内存区域
Mnky 2008-02-22
  • 打赏
  • 举报
回复
char tmp[20]="abc" 是定义一个数组,然后让他的值等于"abc";
char *tmp="abc" 是在常量区开辟一个"abc"常量,然后将tmp指针指向该常量。
也就是说,前者的"abc"是复制的,后者的"abc"是原版的。

同样,std::string a="abc"; pTest=(char*)a.c_str(); 并不是将 pTest直接指向了"abc",而是先将"abc"复制给了string a,使得a的值为"abc",然后用pTest去指向a的值。所以如果a不存在了,pTest既然就不对了。
而 char*p="abc";pTest=p; 之后,p和pTest都直接指向常量区的原版"abc",所以出了test()函数作用区,对常量区依然没有影响。
白乔 2008-02-22
  • 打赏
  • 举报
回复
to 12搂:

试试

	char * cp1 = "abc";
char * cp2 = "abc";
char cp3[] = "abc";
char cp4[] = "abc";

cout << (void *) cp1 << endl;
cout << (void *) cp2 << endl;
cout << (void *) cp3 << endl;
cout << (void *) cp4 << endl;


--------我是分隔线--------我是分隔线--------我是分隔线--------

学标准的、全面的C++
写笨笨的、健壮的代码
做风趣的、谦逊的程序员

--------《标准C++开发入门与编程实践》
http://books.vcer.net/stdcpp
加载更多回复(7)
微信小程序系统教程[初级阶段],微信小程序0基础学起,讲解微信小程序开发的基础知识。 微信小程序系统教程共有“微信小程序系统教程[初级阶段]”、“微信小程序系统教程[中级阶段]——核心技术”、“微信小程序系统教程[阶段]客服消息+微信支付+九宝电商系统”。 “微信小程序系统教程[阶段]全套课程”包含: 1.微信小程序系统教程[阶段]_客服消息 2.微信小程序系统教程[阶段]_微信支付 3.微信小程序系统教程[阶段]_九宝电商系统 学习“微信小程序系统教程[阶段]”要求有微信小程序的基础。建议先学习“微信小程序系统教程[初级阶段]”、“微信小程序系统教程[中级阶段]”,后在报名“微信小程序系统教程[阶段]”。 阶段讲解的客服消息,是针对小程序的。后台程序用接近底层的技术,没有使用三方技术。这样降低同学们学习成本。 微信支付,这部分课程很有难度,要求同学们认真听讲,有不会的技术问题可以请教老师。购买课程后请联系老师,提供单号,给你源程序。 九宝电商系统是一套十分适和学习、项目的课程。既可以系统的学习微信小程序相关知识,还可以修改后上线。 “微信小程序系统教程[中级阶段]——核心技术”重点讲解微信小程序事件、组件、API 微信小程序系统教程[初级阶段],微信小程序0基础学起,讲解微信小程序开发的基础知识。 购买课程的同学,可赠送就九宝老师编写的《微信小程序开发宝典》。 购课请咨询qq2326321088

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧