带有指针的程序输出

时间:2014-01-30 15:35:43

标签: c pointers

我是c的新手。在执行程序期间,第一个输出显示结果为z,然后第二个输出显示15,但在初始化为long时无法显示结果。任何人都可以解释原因吗?

main()
{
    char c,*cc;
    int i;
    long k;
    k=9999;
    c='z';
    i=15;
    cc=&c;
    printf("%c,%u",*cc,cc); 
    cc=&i;
    printf("\n%d,%u",*cc,cc);
    cc=&k;
    printf("\n%ld,%u",*cc,cc);
}

3 个答案:

答案 0 :(得分:1)

简单的答案是您正在调用未指定的行为。

更长的答案是:

因为系统上的 ,指针与int一样大但小于long

首先是printf:

*cc被提升为intcharshort在用作var-args时会被提升为int

Printf将其打印为char,并按预期显示z

第二次印刷:

*cc指向i中的第一个字节。它被提升为intcharshort在用作var-args时会被提升为int。由于它打印15(而不是0),我们可以告诉您的系统是little-endian

第三次印刷:

*cc指向k中的第一个字节。由于您使用的是小端系统,因此评估为15(9999 = 15 + 39 * 2 ^ 8)。它被提升为intcharshort在用作var-args时会被提升为int

但是,您提供了格式说明符%ld,它需要很长时间。我的猜测是,在你的系统上,long是int的两倍,这意味着它将打印指针值与15结合,这将导致一些大数字。

第二个printf说明符将在当前堆栈帧之外获取4个字节(假设int为32位),这将打印一个(可能不是那么)随机数,否则可能导致分段错误。

注意:

我对你的系统做了一些假设:

8位字符/字节

32位int

32位指针

64位长

答案 1 :(得分:1)

您的程序声明cc是指向char的指针。当*cc指向intlong时使用char时,cc所指的i只需要一个int(一个字节)

您分配给cc的值15适合一个字节。并且,在您的C实现中,i的字节首先与低值字节一起存储,因此,当cc指向k的第一个字节时,它指向包含15的字节。(某些C实现以不同的顺序存储字节; *cc可以指向高值字节而不是低值字节。)

您分配给printf的值9999不适合一个字节。它需要两个字节,低字节为0xf(15),高字节为0x27(39)(因为9999 = 39 * 256 + 15)。

因此,第三个ccchar的值为15.但是,还有另一个问题。由于*ccchar的指针,printfchar。在int使用的可变参数列表中,%ld值会自动提升为printf。但是,说明符long int告诉%u期望%p。你传递的是错误的论点。

当您传递错误类型的参数时,行为不是由C规范定义的。你不应该期望这样做。

此外,void *是用于打印指针的错误说明符。正确的说明符是printf,指针应该转换为k。第三个printf("%d, %p", *cc, (void *) cc); 可以显示cc的最低字节,如果它已更改为:

k

如果您想使用cc显示long int的完整值,则必须将printf("%ld, %p", * (long int *) cc, (void *) cc); 转换为指向cc的指针并使用正确的说明符:< / p>

char

请注意,int只能以这些方式使用,因为指向float的指针由C专门处理。在其他指针类型之间转换,例如指向{{1}}的指针和指向{的指针{1}},不保证以这种方式工作。

答案 2 :(得分:1)

分配cc = &i;cc = &k; 可能不允许,因为它们违反了以下规则(C99 6.5.16.1p1)[http://www.iso-] 9899.info/n1256.html#6.5.16.1p1]:

  

两个操作数都指向兼容类型的限定或非限定版本,        并且左边指向的类型具有指向的类型的所有限定符        权;

在大多数情况下,char既不与int也不兼容long

您的编译器应该警告您(确保您已启用警告)。

在上一个printf中,您还传递了错误类型的参数,int(因为默认参数促销)而不是long%ld需要。

GCC和clang(以及其他人)也会对此发出警告。