打印值,指针和指向值的指针

时间:2018-10-03 13:41:04

标签: c pointers

 p.apply("Read new file", TextIO.read()
            .from("gs://my_bucket/*")
            .withCompression(Compression.GZIP)
            .watchForNewFiles(Duration.standardMinutes(1), Watch.Growth.never()))

此代码的输出为:

#include<stdio.h>
int main()
{   int i;
    int *p;
    p = &i;
    i=5;

    printf("i = %d, p = %P, *p = %d\n",i,p,*p);

    *p=6;
    printf("i = %d, p = %P, *p = %d\n",i,p,*p);

    return 0;
}

在第一条语句和第二条语句中应将* p = 5赋予* p = 6

5 个答案:

答案 0 :(得分:4)

在您的printf中,您尝试显示p = %P%P不存在,因此% P将被忽略并且将像字符串一样打印。

此后,当您尝试打印*p = %d时,不打印变量*p,而是打印p,因为p未被{ {1}}。

正确的printf应该是:

%P

答案 1 :(得分:4)

您已将以下字符串指定为printf()的格式字符串:

i = %d, p = %P, *p = %d

然后您指定要打印的三个元素:

i, p, *p

因此,%d被替换为i中存储的值,符合预期:

i = 5, p = %P, *p = %d

到目前为止一切正常,除了一件事:%P格式不存在。因此,它会被跳过作为说明符,而是打印出来。

然后将第二个%d替换为p中的值, *p,因为第二个%d是下一个有效的说明符,而p是下一个要使用的变量:

i = 5, p = %P, *p = -1009882308

由于没有更多说明符可供使用*p被忽略,并且在编译时会引发警告或错误。

恭喜,您刚刚将p指向的地址打印为int,也就是未定义的行为

那么,我们该如何解决?

%P替换为实际的有效说明符:%p。现在,使用了所有变量和说明符,您的代码将平稳运行。

这是printf()应该打印的内容:

i = 5, p = C3CE6B3C, *p = 5

注意:使用%p打印p的地址,该地址将以十六进制数字显示。

编辑:如 chux 所述,%p需要相应的void*才能正常工作。在p语句中将(void*)强制转换为printf(),如下所示:(void*)p

答案 2 :(得分:2)

您的格式说明符有错字,无法识别。结果,您传递了要打印为整数的指针。应该是这样的:

printf("i = %d, p = %p, *p = %d\n",i,p,*p);

大多数编译器都会为您的代码发出警告。如果不是,请检查是否可以通过警告更严格地更改设置。

答案 3 :(得分:1)

  

为什么下面的C代码的输出是这样的?
  是的,我的编译器警告%P,但如果我们不关注%P,则还要警告* p,它应返回值i,即5和6 comment

关键问题是假设警告后的代码表现良好。

该警告是由于使用无效的打印说明符"%P"导致的。这会导致不确定的行为(UB)。其余代码不再具有任何指定的行为。因此,C不支持“应该返回值,即5,然后是6”。输出可能是任何东西。


使用有效的打印说明符和匹配的参数。

使用"%p"打印void*。要将p转换为void*,请进行强制转换。

// printf("i = %d, p = %P, *p = %d\n",i,p,*p);
printf("i = %d, p = %p, *p = %d\n", i, (void*)p, *p);

答案 4 :(得分:0)

%P不是有效的转换说明符,因此您的第二个参数p使用%d打印为十进制整数,而*p则根本不打印。

将两行都更改为

printf("i = %d, p = %p, *p = %d\n",i, (void *)p,*p);
                     ^
                     |
                     +---- note lower case p here

,您将获得期望的输出。