为什么某些文件指针在64位操作系统上具有28位地址?

时间:2015-10-06 13:31:35

标签: c

我是编程的新手,有一个让我烦恼的不重要但令人困惑的问题。

让我先发布我的代码:

FILE *fp;
int i;

fp=fopen("test_data.txt", "r");
printf("i's address=%p\n", &i);
printf("fp's address =%p\n", fp);
printf("stdout's address=%p\n", stdout);
close(fp);

输出结果为:

i's address=0x7ffd038ab8cc
fp's address=0x231c010
stdout's address=0x7fbb2e4f7980

我的问题是为什么fp的地址是28位?它不应该与普通变量和标准输出(48位)相同吗?

我在64位Ubuntu Linux上使用GCC。

感谢您的回答!

3 个答案:

答案 0 :(得分:3)

这里最可能的情况是你的文件地址只是以零开头,默认情况下会省略。

编辑:Here是一个指向类似问题的问题。

答案 1 :(得分:2)

fopen可能会致电malloc以获取其FILE*句柄。

malloc的一些实现正在分配" small"对象和"大"对象不同 - 在mmap(2)中列出的不同地址空间段(使用system call或其他syscalls(2)获得)

在某些实现中,stdout是指向某些静态数据的指针...

此外,您可能已启用ASLR ...

您可以在正在运行的进程中使用pmap(1)进行调查。另见proc(5);如果您有空闲时间,请从程序中的/proc/self/maps开始按顺序读取行,并将其复制到stdout;另请尝试cat /proc/$$/maps了解您的shell virtual address space

你也可以strace(1)你的程序来理解它正在做的许多系统调用....

但你真的不应该打扰。从C角度来看,地址或多或少是随机的(除非您深入了解实现细节)

(在某些x86-64处理器上,实际上只有48位地址,最高16位全为零或全部为。)

答案 2 :(得分:2)

如您所知,所有变量的地址,指针通常以十六进制格式存储。

如果您直接转换0x231c010(基数为16),您将获得类似0000 0010 0011 0001 1100 0000 0001 0000(基数2)的内容

转换为您提供32位值。

如果您熟悉计算机的体系结构,您可能知道所有数据路径(用于在计算机内部的各种组件之间传输数据,如ram到处理器等)使用名为" Sign Extender"的设备。

C编译器实际上只产生32位值,但是这些符号扩展器为它增加了额外的0到64位,因此处理器可以对它进行处理。处理结束后,即使您有64位操作系统,程序也会为您提供32位地址。除非您使用本机64位应用程序(不是64位可兼容的应用程序),否则您将始终获得32位地址。