为什么*p0的值每次在编译中都有不同的值。这是用c语言解决这个问题的代码。? 要打印指针,请使用%p并将参数强制转换为(void*)

为什么*p0的值每次在编译中都有不同的值。这是用c语言解决这个问题的代码。? 要打印指针,请使用%p并将参数强制转换为(void*),c,pointers,C,Pointers,像 阅读p+1,即执行*(p+1),是未定义的行为,因为p+1不指向int。所以不要那样做 在评论中,OP询问: p=6487564*p=500 p+1=6487568*(p+1)=0 p0=6487564*p0=-12 这就是我得到的输出,为什么*p0是-12pz解释 十进制值500与十六进制值0x000001F4相同。在little endian机器(32位int)上,其存储方式如下: printf("p=%p\n*p=%d", (void*)p, *p); 然后分配p

  • 阅读
    p+1
    ,即执行
    *(p+1)
    ,是未定义的行为,因为
    p+1
    不指向
    int
    。所以不要那样做 在评论中,OP询问:


    p=6487564*p=500 p+1=6487568*(p+1)=0 p0=6487564*p0=-12 这就是我得到的输出,为什么*p0是-12pz解释

    十进制值500与十六进制值0x000001F4相同。在little endian机器(32位
    int
    )上,其存储方式如下:

    printf("p=%p\n*p=%d", (void*)p, *p);
    
    然后分配
    p0
    p
    值,因此

    p -> F4 01 00 00
    
    因此
    p0
    指向0xF4(假设为8位字符)

    在有符号字符的机器上,十六进制值0xF4是十进制值-12(即有符号8位2的补码表示)

    结论在带有签名8位字符的little endian机器上,打印值将为
    -12

    如果你改变

    p -> F4 01 00 00
         ^
         |
         p0
    

    然后它将打印244。这可能更容易理解,因为500是256+244(或十六进制:0x1F4=0x100+0xF4)

  • 要打印指针,请使用
    %p
    并将参数强制转换为
    (void*)
  • 阅读
    p+1
    ,即执行
    *(p+1)
    ,是未定义的行为,因为
    p+1
    不指向
    int
    。所以不要那样做 在评论中,OP询问:


    p=6487564*p=500 p+1=6487568*(p+1)=0 p0=6487564*p0=-12 这就是我得到的输出,为什么*p0是-12pz解释

    十进制值500与十六进制值0x000001F4相同。在little endian机器(32位
    int
    )上,其存储方式如下:

    printf("p=%p\n*p=%d", (void*)p, *p);
    
    然后分配
    p0
    p
    值,因此

    p -> F4 01 00 00
    
    因此
    p0
    指向0xF4(假设为8位字符)

    在有符号字符的机器上,十六进制值0xF4是十进制值-12(即有符号8位2的补码表示)

    结论在带有签名8位字符的little endian机器上,打印值将为
    -12

    如果你改变

    p -> F4 01 00 00
         ^
         |
         p0
    


    然后它将打印244。这可能更容易理解,因为500是256+244(或十六进制:0x1F4=0x100+0xF4)。

    在尝试访问
    *(p+1)
    时,您正在调用未定义的行为。好的,从技术上讲,在打印带有
    %d
    的指针值时也会调用它
    %d
    不是指针的正确格式字符串。可能您有64位指针和32位整数,因此您在第二个%d中得到了指针的剩余部分,但这都是未定义的行为。但是编译器没有对此发出警告吗?
    printf(“p=%d\n*p=%d”,p,*p)->
    printf(“p=%p\n*p=%d”,(void*)p,*p)否在这种情况下,我的编译器不会发出警告..p=6487564*p=500 p+1=6487568*(p+1)=0 p0=6487564*p0=-12尝试访问
    *(p+1)
    时,您正在调用未定义的行为。好的,从技术上讲,在打印带有
    %d
    的指针值时也会调用它
    %d
    不是指针的正确格式字符串。可能您有64位指针和32位整数,因此您在第二个%d中得到了指针的剩余部分,但这都是未定义的行为。但是编译器没有对此发出警告吗?
    printf(“p=%d\n*p=%d”,p,*p)->
    printf(“p=%p\n*p=%d”,(void*)p,*p)否我的编译器在这种情况下不会给出警告..p=6487564*p=500 p+1=6487568*(p+1)=0 p0=6487564*p0=-12我认为在打印时将指针强制转换为
    void*
    并不是真的必要。@GabrielStaples它在大多数没有强制转换的系统上工作,但要符合标准,强制转换是必需的。我明白了。for
    printf()
    表示预期的参数类型也是
    void*
    。我以前从未注意到这一点,就像我通常看到的那样。@GabrielStaples比cplusplus好得多。不管怎么说,标准是最值得一看的地方。在
    %p
    的标准描述中,您会发现:“……相应的参数应该是指向void的指针……”@Gabriel Staples如果您认为没有必要使用void*,那么请展示一个简单的代码示例。我不认为在打印时将指针投射到
    void*
    。@Gabriel Staples它可以在大多数没有投射的系统上工作,但要符合标准,投射是必需的。我明白了。for
    printf()
    表示预期的参数类型也是
    void*
    。我以前从未注意到这一点,就像我通常看到的那样。@GabrielStaples比cplusplus好得多。不管怎么说,标准是最值得一看的地方。在
    %p
    的标准描述中,您会发现:“……相应的参数应该是指向void的指针……”@Gabriel Staples如果您认为void*是不必要的,那么展示一个简单的代码示例