【问题标题】:Printing address a pointer points to, value the address points to, and the address of the pointer itself打印指针指向的地址、地址指向的值以及指针本身的地址
【发布时间】:2015-05-12 06:36:23
【问题描述】:

我写了一个小程序来让自己更熟悉指针和它们之间的关系。为了做到这一点,我编写了一小段代码,它只声明和初始化一个整数a,然后声明一个指向a 地址的指针*p,然后更深入地分配一个指向指针@ 的指针987654324@ 等等,一直到****pppp。如果我正确理解了指针,那么一个指向...的指针的指针基本上是这样工作的:

Address of pointer (or integer) itself: 0x7fff08d1c658    0x7fff08d1c660    0x7fff08d1c668    0x7fff08d1c670    0x7fff08d1c67c
                                              ↑                 ↑                  ↑                ↑                 ↑ 
                                             pppp     -->      ppp       -->      pp      -->       p       -->       a = 42
                                              ↓                 ↓                  ↓                ↓                 
Address pointer points to:              0x7fff08d1c660    0x7fff08d1c668    0x7fff08d1c670    0x7fff08d1c67c

对角线上的地址必须相同,因为前一个指针总是指向它所分配的下一个指针的地址。现在我想在使用printf()调用的程序中检查这一点,在这里我不确定我打印地址的方式是否更精细的指针**pp***ppp****pppp指向以及我如何打印地址这些指针本身是正确的。有人可以指出可能的错误吗?以下是代码及其输出:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a;
    int *p;
    int **pp;
    int ***ppp;
    int ****pppp;

    a = 42;

    /* Take the address of a */
    p = &a;

    /* Take the address of p */
    pp = &p;

    /* Take the address of pp */
    ppp = &pp;


    /* Take the address of ppp */
    pppp = &ppp;

    printf("Address of int &a:                             %p\n", &a);
    printf("value of a:                                    %d\n\n", a);

    printf("Address where p points to via (void *)p:       %p\n", (void *)p);
    printf("Value that *p points to via *p:                %d\n", *p);
    printf("Address of *p itself via (void *)&p:           %p\n\n", (void *)&p);

    printf("Address where pp points to via (void *)pp:     %p\n", (void *)pp);
    printf("Value that **pp points to via **pp:            %d\n", **pp);
    printf("Address of **pp itself via (void *)&pp:        %p\n\n", (void *)&pp);

    printf("Address where ppp points to via (void *)ppp:   %p\n", (void *)ppp);
    printf("Value that ***ppp points to via ***ppp:        %d\n", ***ppp);
    printf("Address of ***ppp itself via (void *)&ppp:     %p\n\n", (void *)&ppp);

    printf("Address where pppp points to via (void *)pppp: %p\n", (void *)pppp);
    printf("Value that ****pppp points to via ****pppp:    %d\n", ****pppp);
    printf("Address of ****pppp itself via (void *)&pppp:  %p\n", (void *)&pppp);

    return EXIT_SUCCESS;
}

输出:


Address of int &a:                             0x7fff08d1c67c
value of a:                                    42

Address where p points to via (void *)p:       0x7fff08d1c67c
Value that *p points to via *p:                42
Address of *p itself via (void *)&p:           0x7fff08d1c670

Address where pp points to via (void *)pp:     0x7fff08d1c670
Value that **pp points to via **pp:            42
Address of **pp itself via (void *)&pp:        0x7fff08d1c668

Address where ppp points to via (void *)ppp:   0x7fff08d1c668
Value that ***ppp points to via ***ppp:        42
Address of ***ppp itself via (void *)&ppp:     0x7fff08d1c660

Address where pppp points to via (void *)pppp: 0x7fff08d1c660
Value that ****pppp points to via ****pppp:    42
Address of ****pppp itself via (void *)&pppp:  0x7fff08d1c658

【问题讨论】:

  • 我不明白你在问什么。您的代码没有任何问题。
  • 在不同的stackoverflow答案和互联网上提到了不同的方法来打印指针的地址本身,我真的不确定我如何打印它们的逻辑是否正确。
  • 您的程序对我来说看起来不错。请记住,当您需要打印指针(地址)时,请使用%p
  • 您需要使用%p 打印出指针,并且参数应该是(void *) 类型。这是唯一的变化
  • 但是无论级别有多深,只需通过(void *) 后跟指针简单地投射指针就足够了?这意味着如果我有一个指针 *****ppppp 并想打印它的地址,我会使用 printf("%p", (void *)ppppp);

标签: c pointers


【解决方案1】:

您的代码大部分是正确的:您了解printf 使用%p 转换说明符打印指针的值。实际输出是特定于实现的,但可以通过 scanf 使用相同的 %p 说明符解析回指针值。

printf("Address of int &amp;a: %p\n", &amp;a); 中有一个小细节你弄错了:当传递给printf 作为%p 说明符的转换值时,指针应该始终转换为void *。原因很微妙:在某些架构上,指向不同类型的指针可能具有不同的表示形式,包括不同的大小,并且可能以不同的方式传递给printf。将指针转换为void * 可确保它以printf 函数所期望的形式和方式传递。

这种转换不是自动的,因为printf 采用可变数量的不同类型的参数,这些参数以特定于vararg 函数的方式传递:例如float 值被转换为@987654335 并作为@987654335 传递@,但是各种指针类型都不会转换成void *,所以你必须用(void *)强制转换显式写这个转换。

具有不同指针表示的体系结构示例现在不太流行,但年长的程序员可能还记得 nearfar 指针的时代以及函数和数据指针大小不同的各种内存模型。

【讨论】:

  • 如果我错了,请纠正我,但我有 90% 的把握,使用最新版本的 GCC 和相对现代的语言设置(尽管它会警告你)。
  • 据我所见,我已经在我的代码中通过(void *) 投射了所有指针(@CoolGuy 指出的数组地址除外)。所以我不太确定我哪里弄错了。 (删除演员表会发出警告,将-pedantic 传递给gcc。)
  • @brauner:很抱歉,我写了一个小细节,我应该更明确一点。我更新了答案。我的意思也是解释需要将指针转换为(void *) 的理由
猜你喜欢
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-11
  • 2012-10-18
  • 2020-06-07
  • 1970-01-01
相关资源
最近更新 更多