24 深入详解C语言字符串存储之谜:指针 vs 数组的内存真相

一、被误解的指针定义:const char *schar *s的本质

在 C 语言中,以下两种定义其实是等价的:

c:

const char *s = "HelloWorld!";  // 推荐写法,明确字符串只读
char *s = "HelloWorld!";        // 等价,但未声明const,存在修改风险

  • 本质:两者都定义了一个指向字符串字面量的指针
  • 关键区别const修饰符只是告诉编译器「禁止通过指针修改内容」,但字符串本身的存储位置与const无关

二、内存地址对比:用数据说话

实验代码:

c

#include <stdio.h>

int main() {
    // 指针指向字符串字面量(只读区)
    char *s1 = "HelloWorld!";
    
    // 数组拷贝字符串到栈区(可修改)
    char s2[] = "HelloWorld!";
    
    // 本地变量(用于地址对比)
    int i = 0;
    
    // 打印地址
    printf("s1指针地址:       %p\n", (void*)&s1);       // 指针本身的地址(栈区)
    printf("s1指向的内容地址: %p\n", (void*)s1);       // 字符串字面量地址(常量区)
    printf("s2数组地址:       %p\n", (void*)&s2);       // 数组首地址(栈区)
    printf("i变量地址:        %p\n", (void*)&i);        // 本地变量地址(栈区)
    
    // 尝试修改(s1会报错,s2可以修改)
    // s1[0] = 'h';  // 错误!修改常量区数据(未定义行为)
    s2[0] = 'h';     // 正确!修改栈区数组数据
    printf("修改后的s2: %s\n", s2);  // 输出:helloWorld!
    
    return 0;
}

运行结果分析:

s1指针地址:       0x7ffd5f4d37a8    // 位于栈区(和i变量地址接近)
s1指向的内容地址: 0x4006d4           // 位于常量区(代码段)
s2数组地址:       0x7ffd5f4d3790    // 位于栈区(紧邻i变量,证明是本地数组)
i变量地址:        0x7ffd5f4d378c    
修改后的s2: helloWorld!              // 栈区数组可修改

核心发现:

  1. 指针变量s1本身在栈区,但它指向常量区的字符串字面量(只读)
  2. 数组s2完全在栈区,初始化时从常量区拷贝数据到栈区(可读可写)
  3. 地址规律
    • 常量区地址通常较小(如0x4006d4),属于程序代码段
    • 栈区地址较大(如0x7ffd5f...),属于运行时内存

三、深度解析:内存四区中的字符串

1. 指针定义:char *s = "xxx"

  • 存储位置
    • 指针变量s:栈区(局部变量)或静态区(全局 / 静态变量)
    • 字符串内容"xxx":常量区(代码段,只读)
  • 特点

    c

    printf("%p %p\n", "abc", "abc");  // 输出相同地址(编译器优化,共享常量)
    
     
    • 相同字符串字面量只会存储一次
    • 通过指针修改会导致未定义行为(写入常量区)

2. 数组定义:char s[] = "xxx"

  • 存储位置
    • 数组变量s:栈区(局部)或静态区(全局 / 静态)
    • 字符串内容:从常量区拷贝到数组空间(栈区 / 静态区)
  • 特点

    char a[] = "abc", b[] = "abc";
    printf("%p %p\n", a, b);  // 输出不同地址(各自拷贝)
    
     
    • 每次定义数组都会独立拷贝数据
    • 可以修改数组元素(操作栈区数据)

四、实战避坑指南

1. 何时用指针?何时用数组?

场景指针char *s数组char s[]
只读字符串首选(配合const不推荐(浪费栈空间)
可修改字符串禁止(指向常量区)必须(在栈区创建拷贝)
字符串长度固定不适用(需手动管理长度)适用(数组长度自动推断)
作为函数参数必须(数组会退化为指针)需传递长度参数

2. 安全写法示例:

// 只读场景(推荐)
const char *msg = "Error: File not found";  // 明确不可修改

// 可修改场景(必须用数组)
char buffer[100];
strcpy(buffer, "Hello");  // 操作栈区数组,安全可写

// 函数参数场景(指针形式)
void process_string(const char *str) {       // 用const保证只读
    // 安全读取str内容
}

3. 致命错误对比:

// 指针修改(未定义行为,可能崩溃)
char *ptr = "test";
ptr[0] = 'T';  // 写入常量区,触发段错误(Segmentation Fault)

// 数组修改(合法操作)
char arr[] = "test";
arr[0] = 'T';  // 写入栈区,正常修改

五、总结:一张图看懂内存布局

内存布局示意图:
+------------------+
| 常量区(代码段)  |  ← "HelloWorld!"等字符串字面量存储在此,只读
+------------------+
| 栈区              |  ← char *s(指针变量)、char s[](数组)、int i等局部变量
+------------------+
| 堆区              |  ← malloc分配的内存(本文未涉及)
+------------------+
| 静态区            |  ← 全局变量、static变量
+------------------+

关键区别:
- 指针:指向常量区(只读),指针变量本身在栈区/静态区
- 数组:拷贝常量区数据到栈区/静态区(可读可写)

六、开发者必须记住的 3 个结论

  1. 字符串字面量是常量:永远存储在常量区,通过指针访问时禁止修改
  2. 数组是数据拷贝:定义数组会在栈区 / 静态区创建独立副本,允许修改
  3. const是保护盾:使用const char *s明确标记只读意图,避免误操作

掌握这些知识,就能在 C 语言中正确处理字符串存储,避免内存错误和未定义行为。下次遇到类似问题,记得回想今天的布局图哦! 🚀

7 附录:

1 图片:

实际上是:
const char *s     ===    char*s   , 实际上是




2.如果改成指针模式:

我们可以发现数组s2的地址和指针中所存放的地址是不一样的,并且和本地变量i的地址是相近的。这说明数组定义的字符串和指针定义的字符串存放的位置是不一样的,通过数组定义的字符串也可以进行修改。



3.总结:

1 char* c1="HelloWorld!"中,c1指向代码段中的常量,只读不写,且常量相同,指向的地址也相同!!!


2 char c2[]="HelloWorld!"中,c2指向堆栈段中的数据,可读可写,相当于把代码端的数据拷贝了出来!!!

同步定位与地图构建(SLAM)技术为移动机器人或自主载具在未知空间中的导航提供了核心支撑。借助该技术,机器人能够在探索过程中实时构建环境地图并确定自身位置。典型的SLAM流程涵盖传感器数据采集、数据处理、状态估计及地图生成等环节,其核心挑战在于有效处理定位与环境建模中的各类不确定性。 Matlab作为工程计算与数据可视化领域广泛应用的数学软件,具备丰富的内置函数与专用工具箱,尤其适用于算法开发与仿真验证。在SLAM研究方面,Matlab可用于模拟传感器输出、实现定位建图算法,并进行系统性能评估。其仿真环境能显著降低实验成本,加速算法开发与验证周期。 本次“SLAM-基于Matlab的同步定位与建图仿真实践项目”通过Matlab平台完整再现了SLAM的关键流程,包括数据采集、滤波估计、特征提取、数据关联与地图更新等核心模块。该项目不仅呈现了SLAM技术的实际应用场景,更为机器人导航与自主移动领域的研究人员提供了系统的实践参考。 项目涉及的核心技术要点主要包括:传感器模型(如激光雷达与视觉传感器)的建立与应用、特征匹配与数据关联方法、滤波器设计(如扩展卡尔曼滤波与粒子滤波)、图优化框架(如GTSAM与Ceres Solver)以及路径规划与避障策略。通过项目实践,参与者可深入掌握SLAM算法的实现原理,并提升相关算法的设计与调试能力。 该项目同时注重理论向工程实践的转化,为机器人技术领域的学习者提供了宝贵的实操经验。Matlab仿真环境将复杂的技术问题可视化与可操作化,显著降低了学习门槛,提升了学习效率与质量。 实践过程中,学习者将直面SLAM技术在实际应用中遇到的典型问题,包括传感器误差补偿、动态环境下的建图定位挑战以及计算资源优化等。这些问题的解决对推动SLAM技术的产业化应用具有重要价值。 SLAM技术在工业自动化、服务机器人、自动驾驶及无人机等领域的应用前景广阔。掌握该项技术不仅有助于提升个人专业能力,也为相关行业的技术发展提供了重要支撑。随着技术进步与应用场景的持续拓展,SLAM技术的重要性将日益凸显。 本实践项目作为综合性学习资源,为机器人技术领域的专业人员提供了深入研习SLAM技术的实践平台。通过Matlab这一高效工具,参与者能够直观理解SLAM的实现过程,掌握关键算法,并将理论知识系统应用于实际工程问题的解决之中。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值