当前位置: 首页 > article >正文

C++ char*和char[] 可能指向的内存区域详解(附实验)

C++ char* 指向的内存区域详解

  • 写在前面
    • c++内存结构简介
    • 指针常量和常量指针简介
    • 情况一:char* 指向栈区内容
    • 情况二:char* 指向堆区内容
    • 情况三:char* 指向常量区内容
    • 情况四:char* 指向静态区内容
    • 情况五:char* 指向全局区内容
    • 测试代码
  • 写在后面

写在前面

之前调用别人的API,这个API返回一个const char*,当时就在想要不要自己copy一下这个值,因为不知道这个const char什么时候会被释放。于是自己下来探索了一下一个函数返回char时,char*可能指向的内存区域。

c++内存结构简介

C++ 内存主要分为栈区、堆区、全局区、静态区、常量区、代码区。
栈区:主要存放函数的形参、局部遍历
堆区:存放new出来的对象
全局区:存放全局变量
静态区:存放静态变量
常量区:存放常量(不包含局部常量)
我们知道字符串常量,例如"1234"、"abcd"这些值是存放在常量区的。
在这里插入图片描述

指针常量和常量指针简介

指针常量,例如const char * a,const修饰的是*,因此a指向的内容是不可以改的,也就是用a修改值是不可以的。而a本身是可以修改的,a可以指向其他地址。
常量指针,例如char * const a,const修饰的是a,因此a本身是是不可以改的,a不可以指向其他地址。而
a是可以修改的,也就是用*a修改值是可以的。
注意const char * a,只是代表a指向的内容是不可以改,不代表a一定指向的是常量,a也可以指向变量,只是无法修改这个变量的值,例如下面的语法都是合法的

char a[] = "123";
const char* p = a;//p指向变量
const char* p1 = "123";//p指向常量

情况一:char* 指向栈区内容

以下3种赋值方法在函数中定义时,a都是指向栈区。
编译器会把"123"从常量区复制一个副本出来然后赋值给char a[]

 char a[] = "123";//指向栈区
 char a[4];//指向栈区
    a[0] = '1';
    a[1] = '2';
    a[2] = '3';
    a[3] = '\0';
 const char a[] = "123";//指向栈区,不能用 a[0] = '1'; 因为是const

char* a = "123"呢?其实这种赋值方法是错误的,因为"123"的类型是常量const char *,无法讲常量赋值给变量的。
在这里插入图片描述

情况二:char* 指向堆区内容

用new 的方法,这时a指向的是堆区的1、2、3

 char* a = new char[4];//指向堆区
    a[0] = '1';
    a[1] = '2';
    a[2] = '3';
    a[3] = '\0';

情况三:char* 指向常量区内容

指向常量区,“123”就存放在常量区,因此a此时指向的是常量区

const char* a = "123";//指向常量区,不能用 a[0] = '1'; 因为是const

char* a = "123"呢?其实这种赋值方法是错误的,因为"123"的类型是常量const char *,无法讲常量赋值给变量的。
在这里插入图片描述

情况四:char* 指向静态区内容

static char a[] = "123";//指向静态区
static const char a[] = "123";//指向静态区

同样也无法static char* a = "123",原因和情况三一样,a是静态变量而"123"是常量,出发用 static const char* a = "123";

情况五:char* 指向全局区内容

讲变量定义在类外时,a2指向的就是全局区

char a2[] = "123"; //全局区
const char a1[] = "123"; //全局区

需要注意的是const char* a1 = "123";即便在类外定义,同样a1*指向的是常量区。

测试代码

用6个函数测试一下,可以看到指向栈区的指针都因为函数的出栈而被释放了。
在这里插入图片描述

char* Func1() {
    char a[] = "123";//指向栈区
    return a;
}

char* Func2() {
    char a[4];//指向栈区
    a[0] = '1';
    a[1] = '2';
    a[2] = '3';
    a[3] = '\0';
    return a;
}

const char* Func3() {
    const char a[] = "123";//指向栈区
    // 不能用 a[0] = '1'; 因为是const
    return a;
}

char* Func4() {
    char* a = new char[4];//指向堆区
    a[0] = '1';
    a[1] = '2';
    a[2] = '3';
    a[3] = '\0';
    return a;
}

const char* Func5() {
    const char* a = "123";//指向常量区
    // 不能用 a[0] = '1'; 因为是const
    return a;
}

char* Func6() {
    static char a[] = "123";//指向静态区
    return a;
}

const char* a1 = "123"; //指向全局区
const char a2[] = "123"; //指向全局区
const char* a3 = "123"; //指向常量区



int main(int argc, char const* argv[]) {
    char* p1 = Func1();
    const char* p11 = Func1();
    char* p2 = Func2();
    const char* p3 = Func3();
    const char* p4 = Func4();
    const char* p5 = Func5();
    const char* p6 = Func6();

    cout << p1 << std::endl; // 烫烫烫烫烫烫烫烫烫烫
    cout << p11 << std::endl;// 烫烫烫烫烫烫烫烫烫烫
    cout << p2 << std::endl;// 烫烫烫烫烫烫烫烫烫烫
    cout << p3 << std::endl;// 烫烫烫烫烫烫烫烫烫烫
    cout << p4 << std::endl;// 123
    cout << p5 << std::endl;// 123
    cout << p6 << std::endl;// 123
    cout << a1 << std::endl;// 123
    cout << a2 << std::endl;// 123

    delete[] p4;
}

写在后面

臭猴子,你说这山岭外的世界,究竟是什么样的
在这里插入图片描述


http://www.kler.cn/a/307907.html

相关文章:

  • Python 编程入门指南(一)
  • Python Plotly 库使用教程
  • ESLint 使用教程(五):ESLint 和 Prettier 的结合使用与冲突解决
  • 如何使用 Web Scraper API 高效采集 Facebook 用户帖子信息
  • 信号-3-信号处理
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • 使用随机森林模型在digits数据集上执行分类任务
  • 基于鸿蒙API10的RTSP播放器(三:底部视频滑轨进度显示)
  • 基于python+django+vue的学生管理系统
  • Python 课程13-机器学习
  • CSS调整背景
  • 文档内容识别系统源码分享
  • 绘制简单的激波的图
  • 【数据结构】字符串与JSON字符串、JSON字符串及相应数据结构(如对象与数组)之间的相互转换
  • 基于深度学习,通过病理切片直接预测HPV状态|文献速递·24-09-16
  • web技术栈总体概念
  • 有关C# .NET Core 过滤器的使用
  • vue part 11
  • string的模拟实现and友元
  • Jacoco的XML报告详解
  • 链动321模式小程序开发源码
  • HTML 和 CSS
  • java项目之基于web的人力资源管理系统的设计与实现(源码+文档)
  • MySQL之安装与基础知识
  • R语言的基础知识R语言函数总结
  • reg和wire的区别 HDL语言