我是编程的新手,有一个让我烦恼的不重要但令人困惑的问题。
让我先发布我的代码:
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。
感谢您的回答!
答案 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位地址。