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

<!-- @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 的地址是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]:
关键的问题没有解决,看来得在 指针方面 再做加强了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值