C/C++的char*到底是个什么东西——char*字符串的内存占用与用法
首先声明,写这个之前看了一些博客,这篇对我的帮助最大,感谢这位博主:https://blog.csdn.net/yahohi/article/details/7427724
为什么要写这篇
最近在写C++作业的时候要写一个Person类,在名字输入的部分遇到了很多困惑;学习C语言已经是一年多之前的事情了,当时还没到计算机专业,所以一些内容学得比较肤浅,包括今天的char*、指针等。
本来想总结一下具体的问题。转念一想,不如直接把char*彻底地分析一下
前置知识——程序运行时的内存使用情况
可以参考这篇,比较简洁 https://www.linuxidc.com/Linux/2017-02/141094.htm
- 栈区(stack):存储函数的参数,局部变量等,由编译器自动分配和释放,;
- 堆区(heap):由程序员申请和释放,主要是new出来的空间,需要手动delete1,变量还是在栈上,但是指向的内容是在堆上;
- 已初始化数据区:已经初始化过的全局变量和静态变量(包括局部静态变量);
- 未初始化数据区:未初始化的全局变量和静态变量,在空间上与已初始化区相邻;
- 文本区:包括代码段、字符串常量、全局常量等。
char*是什么
以写在main函数里的char* p为例,p就是在栈上的一个平平无奇的指针变量,如果说它有什么特别的地方,那就是它是字符类型的,可能跟其他类型的长度有点区别。
指针变量本身是什么无关紧要,重要的是它所指向的位置。
char*的用法
如果写下以下语句:
char *p = "hello";
那么p就指向了一个文本区的字符串常量的首地址,这就为以后p的行为埋下了隐患,如果单纯是读取还好,等到你要改变p的内容的时候,就会出错,因为常量在程序中是不可以改变的!
如果写成以下语句呢?
n = 20;
char *p = new char[n];
strcpy(p,"hello");
delete[] p;
那么就是在堆上给开辟了一片长度为n个字符的空间供p享用。然后给p一个字符一个字符地传入了“hello”这个字符串,并以"\0"结尾。
让我们看看strcpy2函数的内部:
//C语言标准库函数strcpy的一种典型的工业级的最简实现。
//返回值:目标串的地址。
//对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返回值,通常为NULL。
//参数:des为目标字符串,source为原字符串。
char* strcpy(char* des,const char* source)
{
char* r=des;
assert((des != NULL) && (source != NULL));
while((*r++ = *source++)!='\0');
return des;
}
//while((*des++=*source++));的解释:赋值表达式返回左操作数,所以在赋值'\0'后,循环停止。
所以就是一个一个坑一个坑地把值复制了过去,在对指针变量进行赋值时需要注意这一点:不能直接写A=B,这样就成了A指向了B指向的区域(学习指针时,一开始一般都会看到这个内容)。
那么问题来了,如果已经分配了内存空间(new过之后),直接写:
p = "hello"
会怎么样呢?
答案是编译器会报错或者给警告:
warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
出现这个的原因跟上述直接写char* p = “hello” 出错的原因是一样的。
所以说还是用 **strcpy(destination,source) **,或者自己写类似的内容。如果报错说不安全的话,就用更安全的strcpy_s() 吧~