C/C++的char*到底是个什么东西——char*的内存占用与用法

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

  1. 栈区(stack):存储函数的参数,局部变量等,由编译器自动分配和释放,;
  2. 堆区(heap):由程序员申请和释放,主要是new出来的空间,需要手动delete1,变量还是在栈上,但是指向的内容是在堆上;
  3. 已初始化数据区:已经初始化过的全局变量和静态变量(包括局部静态变量);
  4. 未初始化数据区:未初始化的全局变量和静态变量,在空间上与已初始化区相邻;
  5. 文本区:包括代码段、字符串常量、全局常量等。

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() 吧~


  1. C++的写法,对应C语言的malloc–free。 ↩︎

  2. strcpy函数在string.h 或cstring 头文件中,strcpy函数的使用是有一定风险的,当destination的长度小于source时会面临崩溃的危险。 ↩︎

猜你喜欢

转载自blog.csdn.net/DavieChars/article/details/102656368