| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3153 人关注过本帖, 1 人收藏
标题:几个问题,大家解解看
只看楼主 加入收藏
zisefengye
Rank: 5Rank: 5
等 级:职业侠客
帖 子:167
专家分:386
注 册:2010-6-27
收藏
得分:0 
以下是引用Knocker在2010-7-31 23:06:48的发言:

 sizeof还远远未掌握,还得努力,大一吧?
大学早已虚度。企业打杂网管而已。不过是今年突然想学学罢了。
2010-07-31 23:17
广陵绝唱
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:29
帖 子:3607
专家分:1709
注 册:2008-2-15
收藏
得分:0 
时过境迁,物是人非.


老 K 也变了……
2010-07-31 23:25
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
一夜之间,帖子暴涨

我就是真命天子,顺我者生,逆我者死!
2010-08-01 09:59
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
//问题:下面程序的输出是什么?为什么?
  #include <stdio.h>
  #include <stdlib.h>
  int main()
  {
       float a = 12.5;
       printf("%d\n", a);
       printf("%d\n", *(int *)&a);
       system("PAUSE");
       return 0;
  }
// float 占 8个字节, 转换操作符却是 %d,占4个字节,也就是 只输出了 a 的后4个字节,所以是 0了。

我就是真命天子,顺我者生,逆我者死!
2010-08-01 10:03
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
以下是引用Devil_W在2010-7-31 22:32:47的发言:

 
 
 
别TMD扯淡了,这个问题显然就是因为传入的是指针.
多说无益。
哥站在你这一边

我就是真命天子,顺我者生,逆我者死!
2010-08-01 10:15
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
回复 20楼 Devil_W
顶你,

我就是真命天子,顺我者生,逆我者死!
2010-08-01 10:37
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
如果可能,请加精!谢谢,这样能引起更多的人对编程细节的思考和重视!

没想到引起大家这么热烈的讨论,C语言中确实有许多细节需要大家在编程中共同去揭密的。答案如下(这是我给出的,如果有误,欢迎指正):

问题一(较易):
sizeof的返回值类型是size_t,这是个无符号类型。当unsigned int 和int混合运算的时候,由于编译器认为unsigned int的表达长度比较长,它会认为b<=COUNTS-2两侧的值的类型都是以unsigned int的内存布局方式来存储的。等式右侧:counts-2结果类型被认为是unsigned int型的,5在内存中的表示为0x00000005.等式左侧:b的初值-1在内存中的存储为:0xFFFFFFFF,但由于它被认为采用了无符号方式存储,从而b<=COUNTS-2不满足。因此,循环不进入。

各位不难分析:为什么将 COUNTS -2先赋给一个int型的count变量,再将表达式改为b<=count就可以了!;
类似的问题:

  #include<stdio.h>
  #include <stdlib.h>
  #include <string.h>
  int main()
  {
      int b = 10;  
      const char * str = "adfasdfasdfad";  
      int a = (b - strlen(str) ) / 2;
      printf("%d\n", a); //输出的a值不是一个负数,而是一个大正数,照着上面的思路很容易分析出正确的输出结果)
      system("PAUSE");
      return 0;
  }

问题二(较易):
先弄清楚printf返回值的意思,摘自网上的一段英文解释:
Upon a successful return, the printf() function returns the number of characters
printed (not including the trailing '\0' used to end output to strings).
也即,printf返回的是打印的“字符”个数。

语句printf("%d\n",printf("%d",printf("%d",i)));中,
    先执行的是printf("%d", i),它打出是43, 该printf的返回值是2(因为打印了'4'和’3'两个字符)
  再执行printf("%d",printf("%d",i)),显然打印出2,该printf的返回值是1(因为打印了'1'这一个字符)
  再执行最外层的printf,显然它输出的是1。
连起来,输出的是4321。

问题三(此题较易):
统计x的二进制表示中,'1'的个数。

问题四(此题较难)
为了清楚地解答此题,需要了解以下知识:1)浮点数在内存中的存储方式。2)内存的截断带来的问题。
第一个问题大家可以参考:《C语言与程序设计大学教程》一书或网上资料:http://blog.

printf("%d\n", a);语句执行前,由于float型的a处在printf语句中,a的类型会自动提升为double型的。这不是我瞎扯的(When you pass a float as an argument to a variadic function (like printf()), it is promoted to a double,
which is twice as large as a float (at least on most platforms).)
根据上面的资料可以推算出12.5在计算机内部的存储格式为:
01000000 00101001 00000000 00000000 00000000 00000000 00000000 00000000,即0x41 48 00 00 00 00 00 00
在intel类型的机器上,采用的小端(little Endian)存储格式,即低字节在低地址存储。因此,0x41 48 00 00 00 00 00 00中的后四个字节:00 00 00 00存储在低地址。当把0x41 48 00 00 00 00 00 00转换成int型输出时,由于int型数据占用四个字节,因此,只取低四个字节输出(发生了内存截断),而这四个字节里,存储的不就是00 00 00 00吗?因此,printf("%d\n", a);输出的是0!

再来看printf("%d\n", *(int *)&a);,这条语句的解释相对容易一些。
&a取出float型a的地址(此时由于是取地址,a的类型不会转换成double类型),该地址中存储的是12.5在内存中的二进制表示:01000000 00101001 00000000 00000000,(int*)&a把该地址转换成了int型数据的存储地址,*(int *)&a将该地址中的内容取出并转换成int型的值输出,而01000000 00101001 00000000 00000000的十进制数正好是1095237632!

问题五(较易):
指针的大小并不一定都是4!关于指针变量,有两个要点:1)它里面存储的是地址。2)该地址所代表的或说“捆绑”的内存单元是有大小区别的。
如:
  #include <stdio.h>
  #include <stdlib.h>
  int main()
  {
       int a[10];
      
       printf("%d\n", sizeof(a));//输出40,a中存储了数组首地址,该地址”捆绑“了整个数组空间
       printf("%d\n", sizeof(&a));//输出4,&a中存储了数组首地址,该地址”捆绑“了首元素的空间
       printf("%d\n", sizeof(&a[0]));//输出4,&a[0]中存储了数组首地址,该地址”捆绑“了首元素的空间
       system("PAUSE");
       return 0;
  }
  言归正传:函数原型中 void size(int arr[SIZE])定义的形参,int arr[SIZE]虽然似乎指定了大小,但实际上,数组arr是个不完整数据类型,从而sizeof(arr)的输出为4!
    以下代码即可以说明arr是个不完整的数据类型:
  #include <stdio.h>
  #include <stdlib.h>
  #define SIZE 10
  void size(int arr[SIZE]) //等价于void size(int arr[])
  {
       printf("size of array is:%d\n",sizeof(arr));
  }

  int main()
  {
     int arr[100];
     size(arr); //实际参数有100个元素,而形参只指定了10个,显然只有当形参是不完整数据类型时,编译才不会报错!  
     system("PAUSE");
     return 0;
  }

   

2010-08-01 10:58
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
对了,对最后一问补充一点(没什么需要太多争论的,呵),请大家去参考:
http://blog.
2010-08-01 11:03
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
以下是引用BlueGuy在2010-8-1 10:03:29的发言:

//问题:下面程序的输出是什么?为什么?
  #include
  #include
  int main()
  {
       float a = 12.5;
       printf("%d\n", a);
       printf("%d\n", *(int *)&a);
       system("PAUSE");
       return 0;
  }
// float 占 8个字节, 转换操作符却是 %d,占4个字节,也就是 只输出了 a 的后4个字节,所以是 0了。

float可不是占用8个字节!double才占用8字节哟!
2010-08-01 11:06
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
"捆绑" , "不完整的数据类型"
这些名词让哥真的是很蛋疼

我就是真命天子,顺我者生,逆我者死!
2010-08-01 11:09
快速回复:几个问题,大家解解看
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017416 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved