考虑下面非常简单的代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* a = (int*) malloc(10 * sizeof(int));
printf("a = %p, a+1 = %p", a, a+1);
return 0;
}
输出是这样的:
a = 0x127f190, a+1 = 0x127f194
由于int
的大小是4个字节,我假设从上面的结果中,指针值是我的RAM内存中字节的索引。因此,a+1
实际上a
的值增加了sizeof(int) = 4
(字节)。这是对的吗?
如果是,那为什么我从程序中获得32位内存地址?这台机器是64位运行64位版本的Ubuntu。如何让程序打印完整的64位地址?我是否必须使用特殊标志进行编译?
答案 0 :(得分:7)
你的指针是正确的。传统上,内存以字节为单位进行组织和处理,指针指向它们所指向的任何内容的第一个字节(编辑:它们不是必须的,但是在通常的平台和编译器上)。
您没有看到“64位”指针只是因为输出剥离了前导0 :-)如果你执行sizeof(a),很可能在32位系统上得到“4”,并且64位系统上的“8”。
答案 1 :(得分:4)
我的RAM内存上的一个字节的索引
这对于大多数用途来说足够接近,但并不完全准确。它是进程地址空间中一个字节的索引。虚拟地址与物理RAM没有直接关系,有一种称为“虚拟内存管理器”的东西,负责跟踪每个进程中的虚拟地址是指什么物理RAM(以及RAM以外的东西)。
通常你可以忘记这一点,只需将虚拟地址空间视为RAM(或“内存”以保持抽象)。但是不同进程中的相同虚拟地址可以指代不同的物理内存,或者可以通过不同的虚拟地址在不同的进程中引用相同的内存。或者同一进程中的相同虚拟地址可以在不同时间引用不同的物理内存,如果操作系统已经注意到页面暂时没有使用,则将其交换到磁盘,然后再次使用时返回内存。所以它不是RAM本身的“地址”,它只是操作系统提供你的进程的地址,用于引用一些RAM。
答案 2 :(得分:1)
你看到增加4的原因是你为整数分配内存,整数被固定为四个字节长(在Intel Linux gcc中) - 无论你是编译32位还是64位代码。如前所述,您获得的指针指的是虚拟内存地址,而不是物理内存。
如果将int更改为long,则会看到32位代码增加4个字节,64位代码增加8个字节。
此外,如果您查看sizeof(void *)
,它会告诉您指针是32位还是64位。如果你的指针是64位,那么你将获得用%p打印的64位指针。
我编辑了你的程序,在我的Ubuntu副本上运行,添加:
printf("Size of pointer = %d\n", (int)sizeof(void *));
这是输出:
a = 0x2067010, a+1 = 0x2067014
Size of pointer = 8
所以指针确实是64位。
答案 3 :(得分:0)
当您编写int* a = (int*) malloc(10 * sizeof(int));
时,您正在为十个元素的数组分配内存。这相当于int a[10];
,a = 0x127f190
是第一个元素a[0]
的地址。
答案 4 :(得分:0)
对不起,没有给你一个确切的答案。但它来了:
寻找Pointer Arithmetic
,你会发现你正在寻找的所有东西。
即使你的系统运行x64,大多数编译器都默认使用x86,除非你特意声明为x64编译。因此,搜索x64标志的编译器文档,以及相关选项。