我有一个名为'Address'的函数:
template <class Variable> unsigned long Address(Variable *X){
return (unsigned long &) X;
}
此函数返回给定参数的地址。即使给出了论证 它不是变量,它返回一个值,当我将此值指向另一个指针时,我可以访问该值。
当我正在使用这个函数时,我看到这个函数总是在非变量(如“Hello world!”)参数上返回相同的值。
cout << "Address (?) of 'Hello world!' :" << Address("Hello world!") << "\n";
和
cout << "Address (?) of 'Hello world' :" << Address("Hello world") << "\n";
提供相同的输出。但是当我尝试
时cout << "Address (?) of 'Hello world!' :" << Address("Hello world!") << "\n";
cout << "Address (?) of 'Hello world!' :" << Address("Hello world") << "\n";
在同一个文件中执行此操作,输出不同。
这是为什么?
答案 0 :(得分:4)
字符串文字的地址完全依赖于编译器。在您的情况下,您的两个单独的程序每个编译一个*字符串文字参数并最终给它相同的地址。在单程序示例中,有两个单独的文字,它们有两个不同的地址。
当编译器遇到字符串文字时,它会为二进制输出文件留出空间(有时称为“数据段”)。这是二进制文件中专门用于数据而不是可执行代码的位置。根据编译器的决策,它可以选择文件中的不同位置。但是,因为数据在文件内部,所以每次运行时它的地址总是相同的。
在你的第一个例子中,你有两个不同的二进制文件,每个文件只有一个字符串文字,编译器碰巧做出了关于字符串放置位置的相同决定,因此它们都给出了相同的答案。
在第二个示例中,您有一个二进制文件,其中包含两个不同的字符串文字,因此它们当然具有单独的地址。
*从技术上讲,分别有两个和四个文字;我专注于用作函数参数的文字。
答案 1 :(得分:3)
C ++以实现定义的方式将字符串的内容放入内存中。通常,程序的所有字符串都将背靠背放置在一段内存中,'\0'
终止符标记其结尾。实际放置主要取决于编译器,但也取决于是否存在可能放在您要打印的地址之前的其他常量。
这就是为什么来自不同程序的地址的比较毫无意义。编译器可以自由地将字符串文字的表示放在任何位置。
例如,地址可能会因为在程序中添加另一个字符串文字而发生变化。此代码打印的地址
cout << addr("Hello, world!") << endl;
和此代码
cout << "Here is the address: " << addr("Hello, world!") << endl;
但是,来自同一程序的不同字符串文字的地址保证不同。此外,如果翻译单元单独编译然后链接到单个程序中,具有相同内容的字符串文字可能有多个地址。
注意:请勿投放到unsigned long
,但不保证能够正常使用。 Use uintptr_t
instead.