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

相同内容字符串文字的存储是否保证相同?

庾才
2023-03-14

下面的代码安全吗?编写类似这样的代码可能很有诱惑力:

#include <map>

const std::map<const char*, int> m = {
    {"text1", 1},
    {"text2", 2}
};

int main () {
    volatile const auto a = m.at("text1");
    return 0;
}

该映射仅用于字符串文本。

我认为这是完全合法的,似乎正在起作用,但是我从未见过保证在两个不同地方使用的文字指针是相同的。我无法设法让编译器为具有相同内容的文本生成两个单独的指针,所以我开始怀疑这个假设有多坚定。

我只关心相同内容的文字是否可以有不同的指针。或者更正式地说,上面的代码可以除外吗?

我知道有一种方法可以编写代码来确保它有效,我认为上述方法很危险,因为编译器可能会决定为文字分配两个不同的存储,尤其是如果它们被放置在不同的翻译单元中。我说得对吗?

共有3个答案

怀飞扬
2023-03-14

不,C标准不作这样的保证。

也就是说,如果代码在同一个翻译单元中,那么很难找到计数器示例。如果main()在不同的翻译中,那么计数器示例可能更容易生成。

如果地图在不同的动态链接库或共享对象中,那么几乎可以肯定情况并非如此。

易失性限定符是一个转移注意力的东西。

韦叶秋
2023-03-14

该标准不保证具有相同内容的字符串文字的地址是相同的。事实上,[lex.string]/16说:

是否所有的字符串文字都是不同的(即,存储在不重叠的对象中),以及字符串文字的连续计算是产生相同的还是不同的对象,都是未指定的。

第二部分甚至说,当第二次调用包含字符串文字的函数时,您可能不会得到相同的地址!尽管我从未见过编译器这样做。

因此,当字符串文字重复时使用相同的字符数组对象是可选的编译器优化。通过安装g和默认编译器标志,我还发现在同一翻译单元中,两个相同的字符串字面值获得了相同的地址。但正如你所料,如果相同的字符串文字内容出现在不同的翻译单元中,我会得到不同的结果。

相关有趣的一点是:不同的字符串也可以使用重叠数组。也就是说,鉴于

const char* abcdef = "abcdef";
const char* def = "def";
const char* def0gh = "def\0gh";

您可能会发现< code>abcdef 3 、< code>def和< code>def0gh都是同一个指针。

此外,这条关于重用或重叠字符串文字对象的规则仅适用于与文字直接关联的未命名数组对象,如果文字立即衰减为指针或绑定到数组引用,则使用该规则。文字也可以用来初始化命名数组,如

const char a1[] = "XYZ";
const char a2[] = "XYZ";
const char a3[] = "Z";

在这里,数组对象< code>a1 、< code>a2和< code>a3是使用文本初始化的,但是被认为不同于实际的文本存储(如果这样的存储甚至存在的话),并且遵循普通的对象规则,因此这些数组的存储不会重叠。

万俟心思
2023-03-14

两个内容完全相同的字符串文本是否是完全相同的对象,这是未指定的,在我看来最好不要依赖。引用标准:

[lex.string]

16 计算字符串文本会生成一个具有静态存储持续时间的字符串文本对象,该对象由上面指定的给定字符初始化。是否所有字符串文本都是不同的(即,存储在非重叠对象中),以及字符串文本的连续计算是否产生相同或不同的对象是未指定的。

如果您希望避免std::string的开销,可以编写一个简单的视图类型(或者在C 17中使用std:∶string_view>),它是字符串文本上的引用类型。使用它来进行智能比较,而不是依赖文字标识。

 类似资料:
  • 问题内容: 拥有Java代码 该字符串将分配在相同的内存位置(或多倍): 是否多次启动同一程序(并行)执行? 可能的答案: 我目前是C#开发人员(尽管在上个千年中使用Java编程)。 我之所以问这个问题,是因为我相信.NET CLR和Java(JVM)之间是相同的,我希望得到.NET应用程序的答案(但由于经常遇到的“应用程序”池术语而引起疑问)。 答案是 字符串 实习生池由同一JVM或.NET C

  • 问题内容: 这是我在采访中遇到的一个问题。 我有两个字符串定义为 我的问题是这两个引用是否指向相同的内存位置。通常,当我们创建相同的字符串(不带new关键字)时,内容是否仅在内存中存储一​​次,并且具有相同内容的所有String对象仅引用同一位置,而没有多余地存储字符串“ Java”?s1和s2的哈希码相同。但是哈希码是否直接取决于对象的内存位置? 问题答案: 合并相同字符串的过程称为“ inte

  • "给定两个字符串s和t,编写一个函数来检查s是否包含t的所有字符(顺序与字符串t相同)。返回true或false。递归不一定。这是我用java写的代码片段。问题是输入: string1="st3h5irteuyarh!"和string2="shrey"它应该返回TRUE,但它返回FALSE。那是为什么?"

  • 问题内容: 通过搜索发现了类似的问题,但我是一位新的(糟糕的)程序员,无法理解答案。 我有一个.txt文件,其中包含多个字符串,以’-‘分隔。我使用拆分将一些字符串分成变量,其中两个相等,但是在if语句中它们不相等。 这将产生以下结果: 瑞典 瑞典 没有 在两个“ Sweden”字符串之前和之后都有一个空格,并且它们都用大写字母“ S”编写,但不相等吗?我在哪里搞砸了? 问题答案: 最后一个元素包

  • 问题内容: 两个具有相同字符的Python字符串a == b,可以共享内存id(a)== id(b),或者可以在内存中两次,id(a)!= id(b)。尝试 Python在这里认识到新创建的“ a” +“ b”与内存中已经存在的“ ab”相同-不错。 现在考虑一个由N个长的州名组成的列表[“ Arizona”,“ Alaska”,“ Alaska”,“ California” …](在我的情况下为

  • 所以基本上我必须检查另一个字符串是否有相同顺序的相同字符。 所以如果血液中的字母和冠状病毒的顺序相同,就像第二个一样,我必须打印阳性。在Java如何做到这一点?提前道谢。