我是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);
}
答案 0 :(得分:1)
简单的答案是您正在调用未指定的行为。
更长的答案是:
因为系统上的 ,指针与int
一样大但小于long
。
首先是printf:
*cc
被提升为int
(char
,short
在用作var-args时会被提升为int
。
Printf
将其打印为char
,并按预期显示z
。
第二次印刷:
*cc
指向i
中的第一个字节。它被提升为int
(char
,short
在用作var-args时会被提升为int
。由于它打印15(而不是0),我们可以告诉您的系统是little-endian。
第三次印刷:
*cc
指向k
中的第一个字节。由于您使用的是小端系统,因此评估为15(9999 = 15 + 39 * 2 ^ 8)。它被提升为int
(char
,short
在用作var-args时会被提升为int
。
但是,您提供了格式说明符%ld
,它需要很长时间。我的猜测是,在你的系统上,long是int的两倍,这意味着它将打印指针值与15结合,这将导致一些大数字。
第二个printf说明符将在当前堆栈帧之外获取4个字节(假设int
为32位),这将打印一个(可能不是那么)随机数,否则可能导致分段错误。
注意:
我对你的系统做了一些假设:
8位字符/字节
32位int
32位指针
64位长
答案 1 :(得分:1)
您的程序声明cc
是指向char
的指针。当*cc
指向int
或long
时使用char
时,cc
所指的i
只需要一个int
(一个字节)
您分配给cc
的值15适合一个字节。并且,在您的C实现中,i
的字节首先与低值字节一起存储,因此,当cc
指向k
的第一个字节时,它指向包含15的字节。(某些C实现以不同的顺序存储字节; *cc
可以指向高值字节而不是低值字节。)
您分配给printf
的值9999不适合一个字节。它需要两个字节,低字节为0xf(15),高字节为0x27(39)(因为9999 = 39 * 256 + 15)。
因此,第三个cc
中char
的值为15.但是,还有另一个问题。由于*cc
是char
的指针,printf
是char
。在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
需要。