打印C指针的值

我们实际使用的变量几乎不可能有100或104这样的地址。不过,变量的地址可以通过打印来确定,如下所示:

int num = 0;
int *pi = #

printf("Address of num: %d Value: %d\n",&num, num);
printf("Address of pi: %d Value: %d\n",&pi, pi);

运行后,会得到下面的输出。在这个例子中我们用了真实的地址,你的地址可能会不一样:

Address of num: 4520836  Value: 0
Address of pi: 4520824  Value: 4520836

printf函数还有其他几种格式说明符在打印指针的值时比较有用,如表1-2所示。

表1-2:格式说明符

格式说明符 含义
%x 将值显示为十六进制数
%o 将值显示为八进制数
%p 将值显示为实现专用的格式,通常是十六进制数

这些说明符的用法如下:

printf("Address of pi: %d Value: %d\n",&pi, pi);
printf("Address of pi: %x Value: %x\n",&pi, pi);
printf("Address of pi: %o Value: %o\n",&pi, pi);
printf("Address of pi: %p Value: %p\n",&pi, pi);

这样就会显示pi的地址和内容,如下所示。在这个例子中,pi持有num的地址:

Address of pi: 4520824  Value: 4520836
Address of pi: 44fb78  Value: 44fb84
Address of pi: 21175570  Value: 21175604
Address of pi: 0044FB78  Value: 0044FB84

%p%x的不同之处在于:%p一般会把数字显示为十六进制大写。如果没有特别说明,我们用%p作为地址的说明符。

在不同的平台上用一致的方式显示指针的值比较困难。一种方法是把指针转换为void指针,然后用%p格式说明符来显示,如下:

printf("Value of pi: %p\n", (void*)pi);

void指针会在null指针和void指针的“void指针”中解释。为了保证示例简单,我们会用%p说明符,而不把地址转换为void指针。

虚拟内存和指针

让打印地址变得更为复杂的是,在虚拟操作系统上显示的指针地址一般不是真实的物理内存地址。虚拟操作系统允许程序分布在机器的物理地址空间上。应用程序分为页(或帧),这些页表示内存中的区域。应用程序的页被分配在不同的(可能是不相邻的)内存区域上,而且可能不是同时处于内存中。如果操作系统需要占用被某一页占据的内存,可以将这些内存交换到二级存储器中,待将来需要时再装载进内存中(内存地址一般都会与之前的不同)。这种能力为虚拟操作系统管理内存提供了相当大的灵活性。

每个程序都假定自己能够访问机器的整个物理内存空间,实际上却不是。程序使用的地址是虚拟地址。操作系统会在需要时把虚拟地址映射为物理内存地址。

这意味着页中的代码和数据在程序运行时可能位于不同的物理位置。应用程序的虚拟地址不会变,就是我们在查看指针内容时看到的地址。操作系统会帮我们将虚拟地址映射为真实地址。

操作系统处理一切事务,程序员无法控制也不需要关心。理解这些问题就能解释在虚拟操作系统中运行的程序所返回的地址。

用间接引用操作符解引指针

间接引用操作符(*)返回指针变量指向的值,一般称为解引指针。下面的例子声明和初始化了numpi

int num = 5;
int *pi = #

然后下面的语句就用间接引用操作符来显示5,也就是num的值:

printf("%p\n",*pi); // 显示5

我们也可以把解引操作符的结果用做左值。术语“左值”是指赋值操作符左边的操作数,所有的左值都必须可以修改,因为它们会被赋值。

下面的代码把200赋给pi指向的整数。因为它指向num变量,200会被赋值给num。图1-5说明了这个操作如何影响内存。

*pi = 200;
printf("%d\n", num);  //显示200

enter image description here

图1-5:利用解引操作符给内存赋值

赞(2)

评论 抢沙发

评论前必须登录!

 

C指针