最近常常遇到字符串相关的考题,于是整理出来了三个常考的知识点。
一、
C/C++中每个字符串都以’\0’作为结尾,这样就能很方便地找到字符串的最后尾部。但由于这个特点,每个字符串都有一个额外字符的开销(如空字符串其实有一个字符’\0’),如果不加以注意就会造成字符串的越界。另外,在进行字符串复制的时候,忘记复制’\0’也会引起错误。关于这方面的实例参考strcpy函数的实现
二、
C/C++为了节省内存,把常量字符串放到一个单独的内存区域,即静态内存区。当几个字符指针被相同的常量字符串赋值时,字符指针都指向常量字符串的首地址,也就是说它们指向了相同的内存地址。但是,用常量字符串初始化数组时,会为数组重新分配内存,并把字符串逐一复制到数组的内存中去,也就是说数组的内存地址与常量字符串的内存地址不同。
为帮助理解,来一道例题,判断以下程序的输出结果是什么,并说明原因。
int main() {
char *str1 = "abc";
char *str2 = "abc";
const char str3[] ="abc";
const char str4[] ="abc";
const char *str5 ="abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout<< ( str1 == str2 )<<" ";
cout<< ( str3 == str4 )<<" ";
cout<< ( str5 == str6 )<<" ";
cout << (str7 == str8 );
}
输出结果为:1 0 1 1
原因:str3,str4是数组,所以它们有各自不同的内存空间;str1,str2,str4,str5,str6,str7为字符指针,所以它们指向了相同的内存地址。
三、
当函数返回值为非引用或指针类型时,返回值不管是局部变量或全局变量,还是静态变量,返回的是值的一个复制。当函数返回值为引用或指针类型时,不能返回局部变量的指针或引用。因为函数执行完毕后会释放分配给局部变量的存储空间,所以函数返回的对局部变量的引用或指针会指向不确定数据的内存。
这个知识点说的有点不清不楚,来看一道例题:
以下两段程序,判断两段程序的输出结果是否相同,如果不相同请说明原因。
程序一
char *getm() {
char p[]=”Hello World”;
return p;
}
int main() {
char *str=NULL;
str=getm();
printf(str);
}
程序二
char *getm() {
char *p=”Hello World”;
return p;
}
int main() {
char *str=NULL;
str=getm();
printf(str);
}
答案是输出不同的结果。程序一输出乱码,程序二输出”Hello World”
程序一用常量字符串”Hello World”初始化数组p,所以编译器为数组p重新分配了内存,并把”Hello World”逐字符复制到了P数组的内存中。但是,getm函数中声明的数组p为局部变量,在执行完getm函数后编译器会释放数组p的内存。getm函数返回的数组p的首地址指向未知数据内存地址。
程序二用常量字符串”Hello World”初始化指针p,所以p指向了存储”Hello World”的静态内存区。执行getm函数不会释放静态内存区的内存,所以getm函数返回的指针指向常量字符串”Hello World”的首地址。