c++ 学习 之 静态存储区域 和常量字符串的联系

2023-09-18 21:58:40

什么是静态存储区域

静态存储区域(Static Storage Area)是计算机程序运行时用于存储全局变量、静态变量和字符串字面值等数据的一种特殊内存区域。静态存储区域具有以下特点:

  1. 生存周期:静态存储区域中的数据在程序启动时分配,在程序结束时才会释放。这意味着这些数据在整个程序的执行期间都存在,不会随着函数的调用而创建或销毁。

  2. 全局性质:静态存储区域中的数据通常具有全局作用域,可以在程序的任何地方访问。这包括全局变量和静态变量。

  3. 不可动态分配:静态存储区域中的内存分配是静态的,不能在运行时动态分配或释放。这与堆(heap)和栈(stack)等内存区域不同,它们可以在程序运行时动态管理内存。

常见的使用静态存储区域的情况包括:

  • 全局变量:全局变量存储在静态存储区域中,它们可以被程序中的任何函数访问。

  • 静态变量:使用static关键字声明的局部变量也存储在静态存储区域中。这些变量在函数调用之间保持其值不变,而不像普通局部变量那样在每次函数调用时重新创建和销毁。

  • 字符串字面值:字符串字面值(例如:“Hello, World!”)存储在静态存储区域中。它们在程序启动时分配,并在整个程序执行期间可用。

静态存储区域的主要优点是它们的生存周期长,使得它们适用于需要在整个程序执行期间保持不变的数据。然而,应该小心使用静态存储区域,因为滥用全局变量和静态变量可能会导致程序的可维护性和可读性下降。

了解常量字符串

常量字符串是指在程序中不可更改的字符串,也称为字符串字面值或字符串常量。在C++中,你可以使用两种方式来创建常量字符串:

双引号括起来的字符串字面值:

const char* str = "Hello, World!";

在上面的例子中,“Hello, World!” 是一个字符串字面值,它被存储在程序的静态存储区域,并且不能被修改。const char*是一个指向字符的指针,用于指向这个常量字符串。这意味着你不能通过 str 指针来修改字符串中的字符。

使用const修饰的字符数组:

const char str[] = "Hello, World!";

这里,const关键字用于修饰字符数组,表示该数组中的内容是不可修改的。这种方式也会将字符串字面值复制到程序的静态存储区域,但它使用字符数组来存储字符串,而不是指针。

补充 :

const char str[] = "Hello, World!"; 
和
 char str[] = "Hello, World!"; 
 有区别吗
const 修饰的数组:
const char str[] = "Hello, World!"; 中的 str 是一个字符数组,并且被声明为 const,
这表示这个字符数组是不可修改的。你不能通过 str 来修改数组中的任何字符。

非 const 数组:
char str[] = "Hello, World!"; 中的 str 也是一个字符数组,但没有被声明为 const。
这意味着你可以使用 str 来修改数组中的字符。例如,你可以这样做:str[0] = 'X'; 来将第一个字符修改为 'X'。
总结:主要区别在于 const 关键字的有无。如果你希望字符串是不可修改的,应该使用 const char[],
而如果你需要修改字符串,可以使用 char[]。在实际编程中,根据需要选择适当的方式来声明字符串。

常量字符串的特点包括:

不能被修改:无论你是使用指针还是字符数组,常量字符串的内容都不能被直接修改。尝试修改常量字符串会导致编译错误。

存储在静态存储区域:常量字符串通常存储在程序的静态存储区域,这意味着它们在程序运行期间一直存在,直到程序结束。

字符串字面值:常量字符串通常是字符串字面值,它们用双引号括起来,例如:“Hello, World!”。

使用const:为了强调字符串的不可修改性,通常会使用const关键字来修饰指针或字符数组的声明。

我们来看一个错误的例子: ( 编译的时候可以过,但是运行的时候不可以)

char* p1 = (char*)"123";
p[1] = '8';

p1 是一个指向字符的指针,它指向一个字符串字面值 “123” 的地址。然而,问题出现在以下这行代码:

p1[1] = '8';

这行代码试图修改字符串字面值 “123” 中的第二个字符,将其改为 ‘8’,但这是不允许的。原因如下:

字符串字面值是常量字符串,它们存储在程序的静态存储区域,被视为只读。试图通过指针来修改字符串字面值的内容会导致未定义的行为,这可能会导致程序崩溃或产生不可预测的结果。

当你将一个字符串字面值强制类型转换为char*时,编译器会允许这个操作,但实际上这只是一种编译器允许的行为,并不表示你可以安全地修改字符串字面值。这种操作是不安全的,因为它试图绕过C++的常量性检查。

如果你需要修改字符串,应该将字符串存储在一个可修改的字符数组中,而不是字符串字面值。例如:

char p2[] = "123";
p2[1] = '8'; // 这是合法的,因为p2是一个字符数组

在这个示例中,p2 是一个字符数组,它存储了字符串 “123” 的拷贝,你可以安全地修改这个字符数组的内容。

我们来看一下一个 强制类型转换

char* p1 = (char*)"123";
cout << p1[0] << endl;

码在语法上是合法的,但它包含了一些不太安全的操作,可能会导致不可预测的行为。让我解释一下:

char* p1 = (char*)"123";

在这行代码中,使用了C风格的强制类型转换 (char*) 将字符串字面值 “123” 的地址赋给了 p1。这是合法的,但需要注意以下几点:

“123” 是一个字符串字面值,存储在程序的静态存储区域,被视为只读。通过 p1 修改这个字符串的内容是不安全的,可能导致未定义的行为。

在C++11之后,C++引入了更安全的字符串字面值常量,它们的类型是 const char[],而不是 char[]。使用 (char*) 强制类型转换会去除了 const 修饰符,这意味着你可以尝试修改这个字符串,但这是不安全的。

更安全的做法是使用 const char* 指针来指向字符串字面值,以明确表示这个字符串是只读的。例如:

const char* p1 = "123";

如果你尝试修改 p1[0] 所指向的字符,这将导致未定义的行为,因为字符串字面值是只读的。因此,尽量不要修改字符串字面值,而是使用合适的数据结构来存储和修改字符串内容。

更多推荐

QUIC协议报文解析(三)

在前面的两篇文字里我们简单介绍了QUIC的发展历史,优点以及QUIC协议的连接原理。本篇文章将会以具体的QUIC报文为例,详细介绍QUIC报文的结构以及各个字段的含义。早期QUIC版本众多,主要有谷歌家的gQUIC,以及IETF致力于将QUIC标准化,即IETFQUIC(iQUIC),还有Facebook家的mvfst

【C刷题训练营】第四讲(打好基础很重要)

前言:大家好,这是c语言刷题训练营的第四讲,打好基础便于对c语言语法与算法思维的提高,感谢你的来访与支持!💥🎈个人主页:​​​​​​Dream_Chaser~🎈💥✨✨刷题专栏:http://t.csdn.cn/baIPx⛳⛳本篇内容:c语言刷题训练营第四讲(牛客网)目录BC23-时间转换解题思路:BC24-总成

魔众文库系统 v5.3.0 小程序激励视频广告、下载收藏喜欢虚拟数量、用户注册站内信和欢迎邮件

魔众文库系统基于文档系统知识,建立平台与领域,打造流量、用户、付费和变现的闭环,帮助您更好的搭建文库系统。魔众文库系统发布v5.3.0版本,新功能和Bug修复累计13项,小程序激励视频广告、下载收藏喜欢虚拟数量、用户注册站内信和欢迎邮件。2023年09月18日魔众文库系统发布v5.3.0版本,增加了以下13个特性:·[

开箱即⽤!HashData 云数仓上线华为蓝鲸应⽤商城

近⽇,经过华为对企业技术、产品和服务能⼒的综合评估,酷克数据企业级云原⽣数据仓库HashData通过与华为OceanStorPacific分布式存储的适配与优化,形成⼀体化解决⽅案,成功上线华为蓝鲸应⽤商城。图1:华为蓝鲸商城HashData产品⻚⾯华为蓝鲸应⽤商城是华为数据存储产品线与合作伙伴联合打造的⼀站式IT应⽤

【无标题】

TCP简单的TCP协议的Python实现,包括服务器和客户端服务器端importsocket#定义服务器地址和端口号server_address=('localhost',8000)#创建TCP套接字server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREA

微服务简介

微服务简介微服务架构是一种软件架构模式,它将一个大型应用程序拆分为一组小型、独立的服务,每个服务都有自己的业务逻辑和数据存储。这些服务可以独立开发、部署和扩展,通常使用HTTP或其他轻量级通信协议进行通信。以下是微服务架构的一些关键特点和概念:微服务独立性:每个微服务都是独立的,拥有自己的数据库、业务逻辑和用户界面。这

MySQL的sql_mode合理设置

MySQL的sql_mode合理设置1、sql_mode设置介绍说明sql_mode是个很容易被忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境必须将这个值设置为严格模式,所以开发、测试环境的数据库也必须要设置,这样在开发测试阶段就可以发现问题。showvariab

用于设计和分析具有恒定近心点半径的低推力螺旋轨迹研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。⛳️座右铭:行百里者,半于九十。📋📋📋本文目录如下:🎁🎁🎁目录💥1概述📚2运行结果🎉3参考文献🌈4Matlab代码实现💥1概述本文可用于设计和分析具有恒定近心点半径的低推力螺旋

亚马逊、沃尔玛测评养号、采退需要解决防关联哪些问题?

大家好我是跨境平台测评养号七年从事经验的珑哥。养号环境软件开发,深度解决平台矩阵养号防关联,砍单,F号问题。今天我给大家讲一下做亚马逊、沃尔玛测评项目需要用到的防关联、防封号环境的一些底层技术原理。这里讲的内容我相信很少有人能掌握,都是一些比较难的IT术技。如果你现在正考虑开始进行测评,那么在了解阶段,我建议你首先仔细

Mybatis自动映射Java对象 与 MySQL8后的JSON数据

文章目录Mybatis自动映射Java对象与MySQL8后的JSON数据1.转化成为正常Json类型1.1JsonTypeHander1.2ListJsonTypeHandler负责List<T>类型1.3实体类1.4mapper1.5测试类2.存储为携带类型的JsonMybatis自动映射Java对象与MySQL8后

散列(哈希)查找的定义,常见的散列函数设计以及处理哈希冲突方法

1.散列表1.散列表的定义散列表(HashTable),又称哈希表。是一种数据结构,特点是:数据元素的关键字与其存储地址直接相关。特点:若不同的关键字通过散列函数映射到同一个值,则称它们为“同义词”。通过散列函数确定的位置已经存放了其他元素,则称这种情况为“冲突”。2.处理冲突的方法1:拉链法(链地址法)用拉链法(又称

热文推荐