不同翻译单元中字符串字面量的内存地址是否相同?

Is the memory address for string literals in different translation units the same?

假设我们有以下cpp文件。

#include <iostream>

int main(){
    const char* p1="hello";
    const char* p2="hello";
    std::cout<<p1==p2;
}

输出

1

我们知道,p1 和 p2 指向相同的内存地址(如果我错了请纠正我)。

现在,假设我们在不同的翻译单元中定义了指针:

//A.cpp
#include <iostream>

const char* pA="hello";

int main(){
    //whatever.
}

//B.cpp
#include <iostream>

const char* pB="hello"; //Same string literal

int whatever(){
    //whatever.
}

我想知道 pApB 指向的内存地址是否仍然相同,如果是,在哪些情况下它们可能会有所不同(比如使用关键字等) ?

如评论中所述,C++ Standard 不强制是否应合并多重定义的相同字符串文字:

5.13.5 String literals        [lex.string]


16    Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above. Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified.

编译器(或链接器)经常提供命令行开关来决定是否合并相同的字符串。例如,MSVC 编译器有“启用字符串池”选项 – /GF 合并,或 /GF- 将它们分开。

使用以下代码单元:

#include <iostream>
extern void other();

int main()
{
    const char* inmain = "hello";
    std::cout << (void*)(inmain) << std::endl;
    other();
    return 0;
}

和(在单独的源文件中):

#include <iostream>

void other()
{
    const char* inother = "hello";
    std::cout << (void*)(inother) << std::endl;

}

使用 /GF 开关构建会产生如下输出(字符串具有相同的地址):

00007FF778952230
00007FF778952230

但是,使用 /GF- 会产生:

00007FF7D5662238
00007FF7D5662230

事实上,即使是您的第一个代码片段(稍作修改,如下所示),其中两个文字都在同一个翻译单元中(甚至在同一个范围内)也会生成两个 不同的 使用 /GF- 选项构建时的对象:

#include <iostream>
#include <ios>

int main()
{
    const char* p1 = "hello";
    const char* p2 = "hello";
    std::cout << std::boolalpha << (p1 == p2) << std::endl;
    // Output: "false" using /GF- or "true" using /GF
    return 0;
}