c语言中带指针程序的输出
我是c的新手。在执行程序的过程中,第一个输出显示结果为z,第二个输出显示15,但在初始化为long时无法显示结果。有人能解释为什么吗c语言中带指针程序的输出,c,pointers,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
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);
}
简单的答案是,您正在调用未指定的行为 一个较长的答案是: 因为,在您的系统上,指针与
int
一样大,但小于long
第一次打印F:
*cc
升级为int
(char
和short
用作变量args时升级为int
)
Printf
将其打印为char
并按预期显示z
第二次打印F:
*cc
指向i
中的第一个字节。它被提升为int
(char
和short
在用作var args时被提升为int
)。由于它打印15(而不是0),我们可以看出您的系统是
第三次印刷f:
*cc
指向k
中的第一个字节。由于您使用的是小端系统,因此计算结果为15(9999=15+39*2^8)。它被提升为int
(char
和short
在用作var args时被提升为int
)
但是,您提供了格式说明符%ld
,它需要很长的时间。我的猜测是,在您的系统上,long是int的两倍,这意味着它将打印指针值加上15,这将导致一些大的数字
第二个printf说明符将获取当前堆栈帧外的4个字节(假设int
为32位),这将打印(可能不是这样)随机数,或者可能导致分段错误
注:
我对您的系统做了一些假设:
8位字符/字节
32位整数
32位指针
64位长您的程序将
cc
声明为指向char
的指针。当使用*cc
指向int
或long
时,从cc
指向的位置只需要一个char
(一个字节)
分配给i
,15的值为一个字节。并且,在C实现中,int
的字节首先与低值字节一起存储,因此,当cc
指向i
的第一个字节时,它指向包含15个字节的字节。(一些C实现以不同的顺序存储字节;cc
可以指向高值字节而不是低值字节。)
分配给k
,9999的值不适合一个字节。它需要两个字节,低字节为0xf(15),高字节为0x27(39)(因为9999=39*256+15)
因此,第三个printf
中的*cc
的值是15。然而,还有另一个问题。由于cc
是指向char
的指针,*cc
是char
。在printf
使用的变量参数列表中,char
值自动提升为int
。但是,说明符%ld
告诉printf
需要长int
。你传递了错误类型的论点
当您传递错误类型的参数时,行为不由C规范定义。你不应该指望这会奏效
此外,%u
是用于打印指针的错误说明符。正确的说明符是%p
,指针应转换为void*
。如果将第三个printf
更改为:
printf("%d, %p", *cc, (void *) cc);
如果要使用cc
显示k
的完整值,则必须将cc
转换为指向long int
的指针,并使用正确的说明符:
printf("%ld, %p", * (long int *) cc, (void *) cc);
请注意,
cc
只能以这些方式使用,因为C专门处理指向char
的指针。其他指针类型之间的转换,例如指向int
的指针和指向float
的指针,不能保证以这种方式工作。赋值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
(由于默认参数提升),而不是%ld
所需的long
GCC和clang(可能还有其他人)也会对此发出警告。您应该刷新最后一个printf.cc的类型是指向char的指针,因此*cc的类型是char