您的位置:首页 > 其它

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

2010-08-01 09:27 309 查看
<!--
@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
的输出结果。假设这些代码运行在intel
cpu, 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
的地址是0x22ccc0
,b
的地址是0x22cca0
,也就是说编译器给b
分配了8
个int
的空间,b[0]
在a[-8]
的位置上,所以a[-4]

的位置是b[4]
,*(t+1)
输出500,

ptr
和t
分别是0x22ccd4
、0x22ccac

5#
wibnmo
:

b
地址为:12ff58

a
地址为:12ff6c

&a+1
的地址为:12ff80
(这里的1

是指a

整个数组)

10
:12ff6c

20
:12ff70

30
:12ff74

40
:12ff78

50
:12ff7c

同样&a-1
为:12ff58
这正是b
数组的起始地址。

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

ptr
为指向12ff80
的指针,ptr-1
为12ff7c,
即元素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 +
1)
。

而我的测试: 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]:

关键的问题没有解决,看来得在 指针方面 再做加强了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐