“写出printf的输出结果”——你能看到什么?

来源:互联网 发布:下载打扑克软件 编辑:程序博客网 时间:2024/04/30 18:05

<!--@page { margin: 2cm }P { margin-bottom: 0.21cm }PRE.western { font-family: "DejaVu Sans Mono", monospace }PRE.cjk { font-family: "DejaVu Sans", monospace }PRE.ctl { font-family: "DejaVu Sans Mono", monospace }A:link { so-language: zxx }-->

  刚才在 CSDN-CSDN社区-C/C++-C语言里面发现了网友们在讨论一个 printf函数输出结果的问题。因为自己最近在看一个和 scanf函数相关的问题,也就进去看了看(原帖链接:http://topic.csdn.net/u/20100801/07/9775eb1c-d6da-4cb1-a968-c16bc72cc958.html?77377)。

-------------------------------------------------------------

下面就网友们的观点进行描述:

楼主: winematrix

  写出(以下程序中)printf的输出结果。假设这些代码运行在intelcpu, 32bit. integer 四个bytes.

//code starts

#include <stdio.h>int main(){int a[5]={10, 20, 30, 40, 50};int b[5]={100, 200, 300, 400, 500};int *ptr = (int *)(&a+1);int *t = (int *)(&a -1);printf("%d  %d  %d /n", *(a+1), *(ptr-1), *(t+1));}
//code ends.


1#:bluejays:

*(a+1) 输出 a[1],也就是20

*(ptr-1) 输出a[4],也就是50
ptr指向a[5]的位置,所以ptr-1就是a[4]

*(t+1)这个就不一定了。t指向a[-5]*(t+1)就是a[-4],这个位置是什么值,我觉得依赖于编译器。

2#
bluejays:

我的编译器a的地址是0x22ccc0b的地址是0x22cca0,也就是说编译器给b分配了8int的空间,b[0]a[-8]的位置上,所以a[-4]
的位置是b[4]*(t+1)输出500,
ptrt分别是0x22ccd40x22ccac

5#wibnmo:
b地址为:12ff58
a地址为:12ff6c
&a+1的地址为:12ff80(这里的1是指a整个数组)
1012ff6c
2012ff70
3012ff74
4012ff78
5012ff7c
同样&a-1为:12ff58这正是b数组的起始地址。
int *ptr = (int *)(&a+1);

ptr为指向12ff80的指针,ptr-112ff7c,即元素50.

int *t = (int *)(&a -1);

t为指向12ff58这块区域的指针,这里正是数组b的区域,t+1即是元素200的地址。
【以上内容在编辑格式上与原帖略有不同,望原作者见谅。】
--------------------------------------------------

以下网友们的问答,我学习总结如下:
[1]:
关于编译后 两个数组 的地址
b地址为:12ff58----a地址为:12ff6c,这里引用 wibnmo网友的分析,没有自己的分析着实不该,这里暂且用以说明问题。)
解释如下:
由于 a[5]   b[5]
同为局部变量,编译器在进行内存分配时,把他们放在了数据栈之上。 而栈的生长方式为向下增长,即在源代码中
出现较晚的变量将会在较低地址上获得自己的存储区域。
[2]:
有关地址运算int *ptr = (int *)(&a+1);int *t = (int *)(&a -1);的问题:

根据网友们的分析,我得出以下结论,
int *ptr=(int *)(&a+1)
所做的是 在以a[]为“格式单元”(0x12ff6c--0x12ff7c)的内存地址之上,加上一个 int *类型长度的内存空间(这里是4
个字节长度),所得的地址(0x12ff80)放入ptr中。
int *t = (int *)(&a -1);

所做的工作同以上分析类似,在此不再说明。

[补—1]
:以上分析不妥,再行分析。
int *ptr=(int *)(&a+1);这里 (&a + 1)经过测试,等价于(0x12FF7F + )
而我的测试: int *t1 = &a,则有0x12FF6C。这是可以理解的。至于上面一行的情况,目前我的解释和原来的讨论大体一致,采用
“格式单元”的说法(有待学习纠正)。不同之处在于所加的内存空间长度为1个字节长度,而不是 int * 类型的长度。
[3]: int *t = (int *)(&a + 1);int t= &a + 1;的区别。
经过测试,在实现的结果上没有区别。至于更多的讨论,这里先不去考虑。
[4]:贴出我的一些测试及其结果:
#include <stdio.h>

int main()

{

int a[5] = {1,2,3,4,5};

int b[5] = {6,7,8,9,a};

int *t1 = &a + 1;

int *t2 = (int *)(&a + 1);

//printf("a==%X;/nb==%X;/nt1==%X;/nt2==%X;/n",&a,&b,&t1,&t2);

//printf("a[0]==%X;/nb[0]==%X;/nt1==%X;/nt2==%X;/n",&a[0],&b[0],&t1,&t2);

//printf("int * ==%d;/na[5]==%X;/nb[5]==%X;/nt1==%X;/nt2==%X;/n",sizeof(int *),&a[4],&b[4],&t1,&t2);

printf("int * ==%d;/na[5]==%X;/nb[5]==%X;/nt1==%X;/nt2==%X;/n",sizeof(int *),&a[4],&b[4],t1,t2);

return 0;

}

// [Conclusions]:

/*------------

<1>

printf("a==%X;/nb==%X;/nt1==%X;/nt2==%X;/n",&a,&b,&t1,&t2);

a==13FF6C;

b==13FF58;

t1==13FF54;

t2==13FF50;

Press any key to continue

<2>

printf("a[0]==%X;/nb[0]==%X;/nt1==%X;/nt2==%X;/n",&a[0],&b[0],&t1,&t2);

a[0]==13FF6C;

b[0]==13FF58;

t1==13FF54;

t2==13FF50;

Press any key to continue

<3>

printf("a[5]==%X;/nb[5]==%X;/nt1==%X;/nt2==%X;/n",&a[4],&b[4],&t1,&t2);

a[5]==13FF7C;

b[5]==13FF68;

t1==13FF54;

t2==13FF50;

Press any key to continue

<4>

printf("int * ==%d;/na[5]==%X;/nb[5]==%X;/nt1==%X;/nt2==%X;/n",sizeof(int *),&a[4],&b[4],&t1,&t2);

int * ==4;

a[5]==13FF7C;

b[5]==13FF68;

t1==13FF54;

t2==13FF50;

Press any key to continue

<5>

printf("int * ==%d;/na[5]==%X;/nb[5]==%X;/nt1==%X;/nt2==%X;/n",sizeof(int *),&a[4],&b[4],t1,t2);

int * ==4;

a[5]==13FF7C;

b[5]==13FF68;

t1==13FF80;

t2==13FF80;

Press any key to continue

-------------*/

[5]:
关键的问题没有解决,看来得在 指针方面 再做加强了。

 

原创粉丝点击