当前位置: 首页 > 知识库问答 >
问题:

转换单元之间的字符串文字地址[重复]

竺和洽
2023-03-14

我想问一下,在翻译单元之间依赖字符串文字地址是否具有可移植性?即:

给定的文件foo。c引用字符串literal“我是literal!”,依赖于其他给定文件中的bar是否正确且可移植。例如,同一字符串literal“I'm a literal!”将具有相同的内存地址?考虑到每个文件都将被转换为单个。o文件。

为了更好地说明,请遵循示例代码:

# File foo.c
/* ... */
const char * x = "I'm a literal!"

# File bar.c
/* ... */
const char * y = "I'm a literal!"

# File test.c
/* ... */
extern const char * x;
extern const char * y;
assert (x == y); //Is this assertion going to fail?

和一个gcc示例命令行:

gcc -c -o foo.o -Wall foo.c
gcc -c -o bar.o -Wall bar.c
gcc -c -o test.o -Wall test.c
gcc -o test foo.o bar.o test.o

在同一个翻译单位呢?如果字符串文字在同一个翻译单元中,这可靠吗?

共有2个答案

梁丘威
2023-03-14

不,你不能期望相同的地址。如果发生了,就会发生。但没有任何强制措施。

§2.14.5/p12

所有字符串文本是否都是不同的(即存储在非重叠对象中)是实现定义的。尝试修改字符串文本的效果是未定义的。

编译器可以随心所欲。如果它们位于不同的翻译单元中,或者即使它们位于同一个翻译单元中,它们也可以存储在不同的地址中,而不管它们是只读内存的事实。

例如,在MSVC上,两种情况下的地址是完全不同的,但同样:没有什么能阻止编译器合并指针的值(即使在只读部分约束被强制的地方也不行)。

邴和雅
2023-03-14

你不能依赖具有相同内存位置的相同字符串文本,这是一个实现决策。C99草案标准告诉我们,与第6.4.5节String文本不同的相同字符串文本是否不同是未指定的:

如果这些数组的元素具有适当的值,则无法确定这些数组是否不同。如果程序试图修改这样的数组,行为是未定义的。

对于C,这在标准草案2.14.5节中涵盖了字符串文本,其中说:

所有字符串文本是否都是不同的(即存储在非重叠对象中)是实现定义的。尝试修改字符串文本的效果是未定义的。

编译器是允许共享字符串的,但是你必须理解它是如何在不同的编译器之间工作的,所以这是不可移植的,并且有可能改变。Visual Studio包括一个字符串池选项

在某些情况下,可能会合并相同的字符串文本以节省可执行文件中的空间。在字符串文本池中,编译器使对特定字符串文本的所有引用都指向内存中的同一位置,而不是让每个引用都指向字符串文本的单独实例。若要启用字符串池,请使用 /GF 编译器选项。

请注意,在某些情况下,它确实符合条件。

gcc确实支持池化和跨编译单元,您可以通过 -fmerge 常量将其打开:

尝试跨编译单元合并相同的常量(字符串常量和浮点常量)。

如果汇编程序和链接程序支持此选项,则此选项是优化编译的默认选项。使用-fno merge常量可以禁止此行为。

注意,尝试和如果的使用…支持它。

至于至少对于C来说不需要将字符串文本池化的基本原理,我们可以从这个存档的comp.std.c关于字符串文本的讨论中看到,基本原理是由于当时实现的多样性:

GCC可能是一个例子,但不是动机。在可ROM数据中使用字符串文字的部分目的是为了支持,呃,ROM。我隐约记得曾使用过几个C实现(在做出X3J11决定之前),其中字符串文字要么自动合并,要么存储在常量数据程序段中。考虑到现有的各种实践以及在需要原始UNIX属性时可以轻松解决的问题,最好不要试图保证字符串文字的唯一性和可写性。

 类似资料:
  • 我目前正在尝试创建一个聊天服务器作为一个分配,并希望每个消息包含一个头。它将包含ipv4地址,后跟一个字母,然后是用户名 我可以很容易地从字节中解码字符串字母,但现在我很难从字节中解码ipv4地址 我只需要一种方法来尝试和解码四个字节的整数到一个字符串或一些沿这些线的东西 谢谢:D

  • 本文向大家介绍用Python将IP地址在整型和字符串之间轻松转换,包括了用Python将IP地址在整型和字符串之间轻松转换的使用技巧和注意事项,需要的朋友参考一下 前言 大家应该都有所体会,对于字符串型的IP存入数据库中,实在是个即浪费空间又浪费性能的家伙,所以可爱的人们想出来将IP转换为整型存储。MySQL中存在INET_ATON() 、INET_NTOA()函数进行IP整型和字符串之间的转换,

  • 问题内容: 是否存在一种普遍接受的技术,可以有效地将JavaScript字符串转换为ArrayBuffers,反之亦然?具体来说,我希望能够将ArrayBuffer的内容写入并读回。 问题答案: 更新 -五年来,规范中现在有了新方法(请参阅下面的支持),可以使用正确的编码在字符串和类型数组之间进行转换。 TextEncoder 该代表: 该接口表示用于特定方法的编码器,即特定的字符编码,例如, ,

  • 问题内容: 有谁知道如何将a转换为Base64字符串,然后将其反转? 我有以下代码;编码之前的原始图像是好的,但是编码和解码后我只能得到空白图像。 问题答案: 迅速 首先我们需要有图像的NSData Swift 2.0 >编码 Swift 2.0 >解码 Swift 3.0 >解码 编码方式 : 解码 : 斯威夫特3.0 目标C iOS7>版本 您可以使用 编码方式 : 解码 : iOS 6.1和

  • 问题内容: 我一直在寻找一种将字符串(以纪元时间)转换为日期的方法。 基本上,我需要使用this:(以字符串形式)并将其放入this:中。 我一直在看strptime和strftime,但似乎都没有为我工作。有什么建议么? 编辑:谢谢,伙计们。我将其转换为int ,将其转换为,然后在其上运行。完美地工作! 问题答案: 如果只有该值是整数而不是字符串,则可以调用。如果只有某种方法可以将字符串转换为整

  • 问题内容: 我正在使用hibernate将对象映射到数据库。客户端(iOS应用程序)向我发送JSON格式的特定对象,我使用以下实用程序方法将其转换为真实的表示形式 但是问题是,在我的pogo中,我将值存储为byte [],如下所示(因为这是存储在数据库中的内容-blob) 当然,现在转换失败了,因为它无法在byte []和String之间进行转换。 这是更改构造函数以接受String而不是字节数组