BG::频繁用到的char*与char[],却理解不足,将已get内容整理至此文,以C++为主,持更。
char* get_str1()
{
char str[] = {"abcd"}; //str在栈上申请空间,将常量内容复制进来
return str;
}
char* get_str2()
{
char *str = {"abcd"}; //"abcd\0"存放在常量区,str在栈上
return str;
}
可以发现,函数get_str1编译时有警告信息:(warning C4172: 返回局部变量或临时变量的地址),这种写法是不对的,虽然编译能通过,可以运行,但是运行的结果不对,两次运行的结果也不一样,但是换成get_str2,即char*,就正确了。
在函数get_str1中,char str[] = { "abcd" },定义的是一个局部变量,该函数返回的是内部局部字符数组str的地址,当函数调用之后该数组被销毁,所以返回的指针是一个已经释放了空间的指针,指向的值不定。
在函数get_str2中,char* str = { "abcd" },先定义一个字符串常量“abcd“,再将指针str指向它,返回值是这个指针,由于字符串常量在编译时分配内存,只有程序退出时才被销毁,所以返回它的地址没有问题。
例子2:
1)char s[5];
s = "abcd"; //编译失败
2)char *s;
s = "abcd"; //编译成功
原因:在1中,s是数组名,当成是常量指针,不可以作为左值修改; 而2中s是一个指针变量,可以将其指向一个常量字符串。
#include <iostream>
using namespace std;
int main(){
int tmpInt = 0;
int *ia = &tmpInt;
cout<<ia<<" "<<*ia<<endl;
char* a = "123";
char* b = "123";
char* c = "456";
cout<<a<<" "<<*a<<endl;
cout<<(a==b)<<" "<<(a==c)<<" "<<(*a == *b)<<" "<<(*a == *c)<<endl;
char a2[] = "123";
char b2[] = "123";
char c2[] = "456";
cout<<(a2==b2)<<" "<<(a2==c2)<<" "<<(a2[0] == b2[0])<<" "<<(a2[0] == c2[0])<<endl;
const char* a3 = "123";
const char* b3 = "123";
const char* c3 = "456";
cout<<(a3==b3)<<" "<<(a3==c3)<<" "<<(*a3 == *b3)<<" "<<(*a3 == *c3)<<endl;
system("pause");
return 0;
}
string不用担心长度问题,但不能改变单个字符,必须借助其他方式曲线实现。
【3】string、char *、char[]的转换
一、string转char*。
主要有三种方法可以将str转换为char*类型,分别是:data(); c_str(); copy();
1.data()方法,如:
string str = "hello";
const char* p = str.data();//加const 或者用char * p=(char*)str.data();的形式
同时有一点需要说明,这里在devc++中编译需要添加const,否则会报错invalid conversion from const char* to char *,这里可以再前面加上const或者在等号后面给强制转化成char*的类型。
下面解释下该问题,const char*是不能直接赋值到char*的,这样编译都不能通过,理由:假如可以的话,那么通过char*就可以修改const char指向的内容了,这是不允许的。所以char*要另外开辟新的空间,即上面的形式。
2.c_str()方法,如:
string str=“world”;
const char *p = str.c_str();//同上,要加const或者等号右边用char*
3.copy()方法,如:
string str="hmmm";
char p[50];
str.copy(p, 5, 0);//这里5代表复制几个字符,0代表复制的位置,
*(p+5)=‘\0’;//注意手动加结束符!!!
二、char * 转string。
可以直接赋值。
string s;
char *p = "hello";//直接赋值
s = p;
这里有一点要说明,当声明了string类型变量s后,用printf("%s",s);是会出错的,因为“%s”要求后面的对象的首地址。但是string不是这样的一个类型。所以肯定出错。
三、string转char[]
这个由于我们知道string的长度,可以根据length()函数得到,又可以根据下标直接访问,所以用一个循环就可以赋值了。
string pp = "dagah";
char p[8];
int i;
for( i=0;i<pp.length();i++)
p[i] = pp[i];
p[i] = '\0';
printf("%s\n",p);
cout<<p;
这里可以直接赋值。