在C和C++中,存储和显示地址之间有什么区别?

11
在C语言中,如果我创建一个变量并像这样打印它的地址:

int a;
int main (void) {
    printf ("%p", &a);
    return 0;
}

输出结果为:00AA

同样的程序在C++中使用以下代码行:

cout << &a << endl;

输出结果为:0x8f970aa

这两者有什么区别?

我使用 Turbo C 编译了这两个程序。


9
C++ 喜欢 0x8f970 ... - Iharob Al Asimi
29
差异恰好为0x8f97000。但是,你真的期望不同的编译器将变量存储在完全相同的位置吗? - r3mainer
7
你应该在使用printf时将其转换为void*类型。 - chris
6
C99标准对于p格式描述符的说明是:“指针的值以一种实现定义的方式转换为一系列打印字符*”,即使您使用Turbo C编译两个程序,即使变量以相同的相对地址布局,也没有特定的原因可以保证两者会产生相同的输出。猜测C版本是打印程序加载地址的偏移量,而不是绝对地址。 - John Bollinger
4
如果任何参数与相应的转换说明不匹配,行为会变得未定义。在C99 §7.19.6.1/9中提到:“%p”表示“该参数应为指向void类型的指针”。请注意,这是需要遵循的规定。 - chris
显示剩余20条评论
4个回答

17

除非您使用一些特殊的、系统特定的链接器文件,否则不能保证您的变量最终会在内存中的哪个地址结束。甚至在同一个编译器上进行多次编译时,它们可能会以不同的方式出现在不同的位置。当然,不同的编译器将表现不同。没有标准规定它们应该如何分配变量。

这与C与C ++无关。两种标准都声明您的变量应该分配静态存储期。所有未显式初始化的静态存储期变量都由C和C++标准保证被初始化为零(例如请参阅C11 6.7.9/10)。

这意味着两种标准间接保证变量分配在.bss段中。但是具体在.bss段的哪个位置是没有明确规定的。

相关问题


1
@BillLynch 好的,理解了,增加了一些澄清。 - Lundin
.bss或Visual C++等价物可以在编译器中设置,查找您的项目的“随机基地址”或“固定基地址”设置。 - AnthonyLambert

5
这个比较没有意义,因为C和C++是不同的语言。此外,即使在同一台机器上使用相同的编译器运行同一种语言的代码,每次运行时可能会得到不同的输出。变量a的内存位置不会总是相同。结果是由实现定义的。
C11: 7.21.6(p8):
“p”参数必须是一个指向void的指针。该指针的值以实现定义的方式转换为一系列打印字符。

1
我确实同意这个问题至少是有问题的,但我不同意比较毫无意义。C和C++中变量的寻址方式可以进行比较,因为它们是不同的语言,所以可以找到一些差异。 - 463035818_is_not_a_number
1
是的,我认为这个表述不太好,因为地址在每次运行时都会有所不同(但并不是因为C和C++是不同的语言)。 - 463035818_is_not_a_number
@tobi303; 这也取决于编程语言。只需在C和C++中编译相同的代码,然后查看效果即可。 - haccks
2
你同意吗,进行比较是有意义的,并且存在可比较的影响。 - 463035818_is_not_a_number
@tobi303; 你为什么想要进行比较? - haccks
1
@tobi303,你没有理解重点。比较没有意义,因为没有什么要求两个程序的输出代表相同的东西。例如,Turbo C的printf()将对应于%p的参数转换为“将参数转换为六个字符序列'0x00AA'”这种实现定义方式。实际上,C版本可能打印地址偏移量而不是绝对地址。 - John Bollinger

2

尝试回答这个问题 - 如果您将C++程序更改为像这样,它们将是相同的。

int a;

int main (void) {

printf ("%p\n", &a);
cout << &a << endl;

return 0;
}

地址将保持不变,这是最重要的!
C++代码将引入更多的库和启动代码以及C++默认静态数据(cout、cerr、cin等),因此地址可能会被推到内存的更高位置。此外,应用程序的起始地址可能会因为使用C或C++而有所不同,或者是随机的。在Visual C++首选项中,您可以设置“随机基地址”或“固定基地址”,从而移动int a的地址。

1
你说的大部分都是对的,但并不需要从你的代码构建程序来输出两行相同的内容。%p格式不一定要输出绝对地址,我也不确定cout.<<(void *)是否需要这样做。无论如何,我怀疑你误诊了问题。C版本不太可能将变量a存储在低至0xAA的绝对地址上,或者C++版本将其存储在距程序中任何其他参考点0x8f970aa字节的偏移量上,所以我认为这两个版本只是在执行不同的操作。 - John Bollinger
1
每个程序都需要duh!和yes no。我只是想表明整个事情都是不相关的。 - AnthonyLambert

0
问题不在语句上,而是两个语句应该在同一个程序中。因为在不同的程序中,它们具有不同的地址。在同一个程序中,它们将打印相同的地址。我知道其中一个是C语句,而另一个是C ++。但你可以在同一个程序中使用两者。

2
不,绝对没有理由认为如果它们出现在同一个程序中,这两个语句会打印相同的行。它们似乎在做不同的事情,也没有任何要求。特别是,C版本极不可能打印绝对地址,因此它可能打印相对地址,而C++版本极不可能打印相对地址,因此它可能打印绝对地址。 - John Bollinger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接