C语言:字符串字面量及其保存位置

相关阅读

C语言icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12423166.html?spm=1001.2014.3001.5482


        虽然C语言中不存在字符串类型,但依然可以通过数组或指针的方式保存字符串,但字符串字面量却没有想象的这么简单,本文就将对此进行讨论。

        字符串字面量保存在静态存储区,所谓静态存储区即表示其值在程序执行前就已存在于可执行文件中。如果更详细地说,字符串字面量可能保存在.rodata section中,所以当尝试使用指针改变一个字符串字面量的值时会出现段错误。需要特别说明的是上面所说的字符串字面量的位置没有任何限制,可以是在函数内,也可以是在函数外,如下面的代码所示。

例1
#include <stdio.h>
char *ptr1 = "abcde";          //"abcde"被添加到.rodata section
int main()
{char *ptr2 = "ABCDE";      //"ABCDE"被添加到.rodata sectionprintf("This is a string"); //"This is a string"被添加到.rodata section
}

        现在我们可以使用gcc编译链接成可执行程序,如下所示。

$gcc test.c -o test

        然后使用readelf命令读取二进制可执行文件test中的信息,注意这里添加了-S选项表示只输出section头的相关信息。

$readelf -S test
There are 31 section headers, starting at offset 0x36c0:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.pr[...] NOTE             0000000000000338  000003380000000000000030  0000000000000000   A       0     0     8[ 3] .note.gnu.bu[...] NOTE             0000000000000368  000003680000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000038c  0000038c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003b0  000003b00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003d8  000003d800000000000000a8  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000480  00000480000000000000008f  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           0000000000000510  00000510000000000000000e  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000520  000005200000000000000030  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000550  0000055000000000000000d8  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000628  000006280000000000000018  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000020  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001040  000010400000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001060  00001060000000000000011b  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         000000000000117c  0000117c000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  000020000000000000000021  0000000000000000   A       0     0     4[19] .eh_frame_hdr     PROGBITS         0000000000002024  000020240000000000000034  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         0000000000002058  0000205800000000000000ac  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003db8  00002db80000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003dc0  00002dc00000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003dc8  00002dc800000000000001f0  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb8  00002fb80000000000000048  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000018  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004018  000030180000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003018000000000000002d  0000000000000001  MS       0     0     1[28] .symtab           SYMTAB           0000000000000000  000030480000000000000378  0000000000000018          29    18     8[29] .strtab           STRTAB           0000000000000000  000033c000000000000001e1  0000000000000000           0     0     1[30] .shstrtab         STRTAB           0000000000000000  000035a1000000000000011a  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),D (mbind), l (large), p (processor specific)

        从上面的信息中可以找到.rodata section的offset(即该section在二进制文件中的偏移)为2000。

        下面使用hexdump命令查看二进制可执行文件文件test中的内容,其中-C选项用于以十六进制单个字节的方式输出并将对应的ASCII码显示在右边。

$hexdump -C test
......
00002000  01 00 02 00 61 62 63 64  65 00 41 42 43 44 45 00  |....abcde.ABCDE.|
00002010  54 68 69 73 20 69 73 20  61 20 73 74 72 69 6e 67  |This is a string|
00002020  00 00 00 00 01 1b 03 3b  30 00 00 00 05 00 00 00  |.......;0.......|
......

        通过以上我们知道字符串字面量一般是保存在可执行文件的.rodata section中,但是否所有字符串字面量都会保存在.rodata section中呢?答案是否定的,如下例所示。

例2
char array1[6] = "aaaaaa";          //"aaaaaa"被添加到.data section作为全局数组的初始值
const char array2[6] = "bbbbbb"     //"bbbbbb"被添加到.rodata section,因为它是只读的数据
int main()
{const char array3[6] = "cccccc" //"cccccc"被添加到.rodata section,无论是否有const修饰
}

        对例2结果的验证在此跳过,交给读者进行。下面进行结果的说明,在上面的代码中,array1是一个有字符串初始值的全局数组,字符串字面量会直接添加到.data section中,即保存全局变量的section,且并不会在.rodata section保存。但array2是一个只读的有字符串初始值的全局数组,字符串字面量还是会被添加到.rodata section。至于array3,它和例1一样,无论是否有const修饰,字符串字面量都是被放在.rodata section。但要注意的是,array3与array2和array1不同,这个数组是保存在栈上的,而数组的值"cccccc"是在程序执行前就在可执行代码中的.rodata段的。在进入main函数后,栈上会开辟空间给array3,然后将.rodata区的代码复制一份到array3栈上的空间,在退出main函数后,栈上空间被自动回收。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/223724.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MLX vs MPS vs CUDA:苹果新机器学习框架的基准测试

如果你是一个Mac用户和一个深度学习爱好者&#xff0c;你可能希望在某些时候Mac可以处理一些重型模型。苹果刚刚发布了MLX&#xff0c;一个在苹果芯片上高效运行机器学习模型的框架。 最近在PyTorch 1.12中引入MPS后端已经是一个大胆的步骤&#xff0c;但随着MLX的宣布&#x…

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)-简化升级版

文章目录 前言正文一、项目简介二、核心代码2.1 pom.xml 依赖配置2.2 ExcelHeadMapFactory2.3 ExcelDataLinkedHashMap2.4 自定义注解 ExcelExportBean2.5 自定义注解 ExcelColumnTitle2.6 建造器接口 Builder2.7 表格工具类 ExcelUtils2.8 GsonUtil2.9 模版类 ExportDynamicCo…

Opencv中的滤波器

一副图像通过滤波器得到另一张图像&#xff0c;其中滤波器又称为卷积核&#xff0c;滤波的过程称之为卷积。 这就是一个卷积的过程&#xff0c;通过一个卷积核得到另一张图片&#xff0c;明显发现新的到的图片边缘部分更加清晰了&#xff08;锐化&#xff09;。 上图就是一个卷…

java8实战 lambda表达式、函数式接口、方法引用双冒号(中)

前言 书接上文&#xff0c;上一篇博客讲到了lambda表达式的应用场景&#xff0c;本篇接着将java8实战第三章的总结。建议读者先看第一篇博客 其他函数式接口例子 上一篇有讲到Java API也有其他的函数式接口&#xff0c;书里也举了2个例子&#xff0c;一个是java.util.functi…

Ubuntu系统如何安装和卸载CUDA和CUDNN

背景 最近在学习PaddlePaddle在各个显卡驱动版本的安装和使用&#xff0c;所以同时也学习如何在Ubuntu安装和卸载CUDA和CUDNN&#xff0c;在学习过程中&#xff0c;顺便记录学习过程。在供大家学习的同时&#xff0c;也在加强自己的记忆。本文章以卸载CUDA 8.0 和 CUDNN 7.05 …

Docker 编译OpenHarmony 4.0 release

一、背景介绍 1.1、环境配置 编译环境&#xff1a;Ubuntu 20.04OpenHarmony版本&#xff1a;4.0 release平台设备&#xff1a;RK3568 OpenHarmony 3.2更新至OpenHarmony 4.0后&#xff0c;公司服务器无法编译通过&#xff0c;总是在最后几十个文件时报错,错误码4000&#xf…

Linux一行命令配置jdk环境

使用方法&#xff1a; 压缩包上传 到/opt, 更换命令中对应的jdk包名即可。 注意点&#xff1a;jdk-8u151-linux-x64.tar.gz 解压后名字是jdk1.8.0_151 sudo tar -zxvf jdk-8u151-linux-x64.tar.gz -C /opt && echo export JAVA_HOME/opt/jdk1.8.0_151 | sudo tee -a …

Diffusion扩散模型学习:图片高斯加噪

高斯分布即正态分布&#xff1b;图片高斯加噪即把图片矩阵每个值和一个高斯分布的矩阵上的对应值相加 1、高斯分布 np.random.normal 一维&#xff1a; import numpy as np import matplotlib.pyplot as pltdef generate_gaussian_noise(mean, std_dev, size):noise np.ran…

【CentOS 7.9 分区】挂载硬盘为LVM操作实例

LVM与标准分区有何区别&#xff0c;如何选择 目录 1 小系统使用LVM的益处&#xff1a;2 大系统使用LVM的益处&#xff1a;3 优点&#xff1a;CentOS 7.9 挂载硬盘为LVM操作实例查看硬盘情况格式化硬盘创建PV创建VG创建LV创建文件系统并挂载自动挂载添加&#xff1a;注意用空格间…

VSCode SSH 连接提示: spawn UNKNOWN

随笔记录 目录 1. 背景介绍 2. 确认问题 : ssh -V 3. 解决问题 3.1 确认本地 ssh.exe 路径 3.2 修改vscode Remote.ssh:Path 3.2.1 设置 Reomte.ssh:Path - 方法一 3.2.2 设置 Reomte.ssh:Path - 方法二 1. 背景介绍 windows 系统vscode ssh remote CentOS7&#xff…

【零基础入门Docker】什么是Dockerfile Syntax

✍面向读者&#xff1a;所有人 ✍所属专栏&#xff1a;零基础入门Docker专栏https://blog.csdn.net/arthas777/category_12455882.html 目录 编写Dockerfile和Format的语法 2. MAINTAINER 3. RUN 4. ADD 6. ENTRYPOINT 7. CMD 8. EXPOSE 9. VOLUME 11. USER 12. ARG …

.NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式

之前写过使用自定义返回类的方式来统一接口数据返回格式&#xff0c;.Net Core webapi RestFul 统一接口数据返回格式-CSDN博客 但是这存在一个问题&#xff0c;不是所有接口会按照定义的数据格式返回&#xff0c;除非每个接口都返回我们自定义的类&#xff0c;这种实现起来不…

Adobe InDesign各版本安装指南

下载链接 https://pan.baidu.com/s/1VWGKDUijTTETU9sVWFjCtg?pwd0531 #2024版本 1.鼠标右击【InCopy2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 InCopy2024(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【Setup…

DevOps系列文章 : 使用dpkg命令打deb包

创建一个打包的目录&#xff0c;类似rpmbuild&#xff0c;这里创建了目录deb_build mkdir deb_build目标 我有一个hello的二进制文件hello和源码hello.c, 准备安装到/opt/helloworld目录中 步骤 在deb_build目录创建一个文件夹用于存放我的安装文件 mkdir helloworld在he…

深入探讨多模态模型和计算机视觉

近年来&#xff0c;机器学习领域在从图像识别到自然语言处理的不同问题类型上取得了显着进展。然而&#xff0c;这些模型中的大多数都对来自单一模态的数据进行操作&#xff0c;例如图像、文本或语音。相比之下&#xff0c;现实世界的数据通常来自多种模态&#xff0c;例如图像…

【Linux】Linux常见指令解析上

目录 1. 前言2. ls指令3. pwd指令4. cd指令3.1 cd常见快捷指令 4. touch指令5. mkdir指令6. rmdir指令 && rm指令 &#xff08;重要&#xff09;6.1 rmdir指令6.2 rm指令 7. man指令 1. 前言 这篇文章我们将详细介绍一下Linux下常见的基本指令。 2. ls指令 语法: ls [选…

系列一、GitHub搜索技巧

一、GitHub搜索技巧 1.1、概述 作为程序员&#xff0c;GitHub大家应该都再熟悉不过了&#xff0c;很多时候当我们需要使用某一项技能而又无从下手时&#xff0c;通常会在百度&#xff08;面向百度编程&#xff09;或者在GitHub上通过关键字寻找相关案例&#xff0c;比如我想学…

Go自定义PriorityQueue优先队列使用Heap堆

题目 分析 每次找最大的&#xff0c;pop出来 然后折半&#xff0c;再丢进去 go写法 go如果想用heap&#xff0c;要实现less\len\swap\push\pop 但可以偷懒&#xff0c;用sort.IntSlice,已经实现了less\len\swap 但由于目前是大根堆&#xff0c;要重写一下less 因此&#xff…

PWM/PFM 自动切换升压型转换器系统(一)

通过对芯片整体设计要求的考虑&#xff0c;搭建全负载高效率升压型 DC-DC 转换器的整体系 统框架&#xff0c;对系统的工作过程和模块电路的功能进行简要阐述&#xff0c;对外围电路的选取进行准确计 算&#xff0c;分析系统的损耗来源&#xff0c;实现高效率的设计目标。 芯片…

机场信息集成系统系列介绍(8):基于视频分析的航班保障核心数据自动采集系统

目录 一、背景 二、相关功能规划 1、功能设计 2、其他设计要求 三、具体保障数据采集的覆盖点 四、相关性能指标要求 1、性能指标要求 2、算法指标要求 一、背景 基于视频分析的航班保障核心数据自动化采集系统&#xff0c;是ACDM系统建设的延伸&#xff0c;此类系统并…