| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3153 人关注过本帖, 1 人收藏
标题:几个问题,大家解解看
取消只看楼主 加入收藏
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
结帖率:0
收藏(1)
 问题点数:0 回复次数:8 
几个问题,大家解解看
以前做过的几个问题,觉得挺有意思,再贴出来,共赏。

////问题:为什么打印不出数组元素?
  #include<stdio.h>
  #include <stdlib.h>
  int array[] = {23,34,12,17,204,99,16};
  #define COUNTS (sizeof(array) / sizeof(array[0]))


  int main()
  {
      int d;

      for(d=-1;d <= (COUNTS-2);d++)
          printf("%d\n",array[d+1]);

      system("PAUSE");
      return 0;
  }


//问题2:下面的程序是合法的吗?如果是,输出是什么?为什么?
#include <stdio.h>
#include <stdlib.h>
int main()
{
        int i=43;
        printf("%d\n",printf("%d",printf("%d",i)));
        system("PAUSE");
        return 0;
}

//问题3:下面的程序是什么作用?原理是什么样的?
#include <stdio.h>
#include <stdlib.h>

int noName(unsigned int x)
{
    int count=0;
    while(x)
    {
         count++;
         x = x&(x-1);
     }
     return count;
 }

int main()
{
        printf("%d\n", noName(167));
        system("PAUSE");
        return 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;
  }

//问题:下面的程序输出结果是什么?为什么?
  #include <stdio.h>
  #include <stdlib.h>
  #define SIZE 10
  void size(int arr[SIZE])
  {
       printf("size of array is:%d\n",sizeof(arr));
  }

  int main()
  {
       int arr[SIZE];
       size(arr);

       system("PAUSE");
       return 0;
  }

搜索更多相关主题的帖子: 解解 
2010-07-31 10:26
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
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
错误总是难免的:)
2010-08-01 11:20
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
指针是分不清,需要的是程序员能分清呀:)呵呵。如果指针不必区分所指向的内存大小,那如何解释下面的代码:
1) int (*p)[10]; //p是一个指向40个字节空间的int型指针
2)
#include<stdio.h>
#include<stdlib.h>
 
int main()
{
    int a[10];
    int (*p)[10] = &a; //这里能是int (*p)[10] = a;吗?能是int (*p)[10] = a[0];吗?
   
    return 0;
}

我个人认为,读老谭的书的人,都会忽视指针是需要考虑它所指向空间的大小的!而如果忽视这一问题,在实际编程时,很多事情都会迷惑,很多情况下,都会埋下“执行时错误”的隐患!
2010-08-01 11:34
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 

float (**def)[10]; //数组指针。数组中每个元素为指向float*指针的指针。
double *(*gh)[10]; //指向数组的指针。数组共有10个元素,每个元素为double型指针。
double (*f[10])(); //数组指针。该数组中包括10个函数指针,每个指针指向一个函数(函数返回值为double,形参无)
int *((*b)[10]);  //指向指针的指针。该指针指向的指针为:指向10个int型元素的数组指针
long (*fun)(int)  //函数指针。所指函数的返回值为long,形参为int
int (*(*F)(int ,int ))(int) //函数指针。所指函数返回一个指向函数指针的指针

见笑。
2010-08-01 12:15
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
另外,请devil_W参考:http://www.cs.helsinki.fi/u/narayana/cprog04/olli-ex4-qn1.txt
及http://www.cs.helsinki.fi/u/narayana/cprog04/
2010-08-01 12:19
BJ_BOY
Rank: 4
等 级:业余侠客
威 望:1
帖 子:77
专家分:225
注 册:2010-2-4
收藏
得分:0 
int (*(*F)(int ,int ))(int) //可能有问题,呵呵,不好意思!
2010-08-01 12:36
快速回复:几个问题,大家解解看
数据加载中...
 
   



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

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