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

为什么(仅)某些编译器对相同的字符串文本使用相同的地址?

蓬高谊
2023-03-14

https://godbolt.org/z/cyBiWY

我可以在MSVC生成的汇编代码中看到两个“一些”文本,但只有一个带有叮当声和gcc。这会导致完全不同的代码执行结果。

static const char *A = "some";
static const char *B = "some";

void f() {
    if (A == B) {
        throw "Hello, string merging!";
    }
}

谁能解释一下这些编译输出之间的差异和相似之处?为什么叮当/gcc 即使在没有请求优化的情况下也会优化某些东西?这是某种未定义的行为吗?

我还注意到,如果我将声明更改为如下所示的声明,clang / gcc / msvc根本不会在汇编器代码中留下任何“一些”。为什么行为不同?

static const char A[] = "some";
static const char B[] = "some";

共有3个答案

郑正文
2023-03-14

编译器是否选择对 AB 使用相同的字符串位置取决于实现。形式上,你可以说你的代码的行为是未指定的。

这两种选择都正确地实现了C标准。

欧阳鸿哲
2023-03-14

其他答案解释了为什么你不能期望指针地址是不同的。然而,您可以很容易地重写它,以保证< code>A和< code>B不相等:

static const char A[] = "same";
static const char B[] = "same";// but different

void f() {
    if (A == B) {
        throw "Hello, string merging!";
    }
}

区别在于< code>A和< code>B现在是字符数组。这意味着它们不是指针,它们的地址必须不同,就像两个整型变量的地址一样。c混淆了这一点,因为它使指针和数组看起来可以互换(< code>operator*和< code>operator[]看起来行为相同),但它们实际上是不同的。比如< code>const char *A = "foo "之类的;a;是完全合法的,但是< code > const char A[]= " bar ";a;不是。

考虑差异的一种方法是,字符A[] = “...”说“给我一个内存块,并用字符填充它......后跟\0“,而字符 *A= ”...“表示”给我一个地址,我可以在其中找到字符...后跟 \0“。

淳于博
2023-03-14

这不是未定义的行为,而是未指定的行为。对于字符串文字,

允许(但不要求)编译器组合存储以存储相等或重叠的字符串文本。这意味着,当通过指针进行比较时,相同的字符串文本可能会或可能不会相等。

这意味着A == B的结果可能是真的,也可能是的,你不应该依赖它。

从标准来看,[字符串]/16:

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

 类似资料:
  • 问题内容: 根据MSDN BOL(在线图书)对SOME的描述| ANY(Transact-SQL), SOME和ANY是等效的。 使用某些| | | | | | | | ANY以使查询更具可读性。 但是 ,这是为什么在TSQL中有两个关键字具有完全相同的目的的 唯一 原因吗? 它们具有相同的功能是否有历史原因? 问题答案: 根据ANSI-92 SQL标准(搜索“ SOME”)。也在这里,文字 我怀

  • 问题内容: 在python2中: 在python3中: 为什么这里有字节? 编辑 : 我认为当字符串具有非ascii字符时,python3会将字节附加到字符串中。(如@Ashraful伊斯兰教所说) 那么如何在python3中避免这种情况呢? 问题答案: 考虑以下代码片段: 使用Python 2运行此命令,然后使用以下命令查看结果: 等等。不出意外;从到128个字节。 对Python 3做同样的事

  • 基本上,我试图比较两个字符串,如下所示; 当用户点击我的“加入”按钮并从textmeshpro输入字段获取房间名称时,OnJoinRoom会触发。总之,我尝试创建room和其他用户类型room名称和连接。当我尝试创建名称为“123”的room并加入“normalString”时,它加入了该room。但当我从roomName获得值并尝试加入时,它失败了。我确定我在输入字段中输入了“123”。下面是控

  • 下面的代码安全吗?编写类似这样的代码可能很有诱惑力: 该映射仅用于字符串文本。 我认为这是完全合法的,似乎正在起作用,但是我从未见过保证在两个不同地方使用的文字指针是相同的。我无法设法让编译器为具有相同内容的文本生成两个单独的指针,所以我开始怀疑这个假设有多坚定。 我只关心相同内容的文字是否可以有不同的指针。或者更正式地说,上面的代码可以除外吗? 我知道有一种方法可以编写代码来确保它有效,我认为上

  • 问题内容: 在以下代码中,我不明白为什么当它属于两个不同的对象时具有相同的ID? 问题答案: 我认为这是正在发生的事情: 取消引用时,将在内存中创建其副本。该存储位置由以下位置返回 由于没有引用到刚刚创建的方法的副本,因此GC将其回收,并且该内存地址再次可用 取消引用时,将在相同的内存地址(可用)中创建它的副本,您可以再次使用该地址。 第二个副本是GCd 如果您要运行一堆其他代码并再次检查实例方法

  • 假设我们有以下代码: 集会示威 全球抄送 4.7.2, 叮当声 3.2, 硬拷贝 13.0.1 未定义对`void foo的引用 MSVC-11.0 无法解析的外部符号" void __cdecl foo 注意第一个输出中的,第二个输出中是。 为什么?谁是对的?你能引用标准吗?