试题集锦

本文深入探讨了C语言中的位运算概念及其应用,包括逻辑移位、算术移位等,并通过实例详细解释了如何计算数组操作的结果。此外,还分析了联合体的内存分配原则及对齐方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.int n=(-1)&12345   
解:12345, -1的二进制是 1111111111111111 (用补码表示,去符号 取反加1)

2.int array[5][3]; array[5]-array[2]=?  
解: 9, 数组相减得到的是值的个数,而不是所需要的空间数。空间数是36,一个int/指针占4个字节。

如:
 main()
{  
     int a[5][5];
     printf("%d/n",&a[0][1]-&a[0][0]);
}
为什么打印结果是 1 而不是 1*sizeof(int) 呢
答:因为指针的运算都是以一个元素为单位, 整形指针就是以一个整型的长度为单位, 数组也是一样。


3.0X4321>>4<<4=?       0x4320
应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。
右移相当于除法,左移相当于乘法

延伸:

逻辑移位(不管是左移位还是右移位)   都是空缺处补0      
  例如:     mov   ax   ,   1100_0111_0110_1000B  
                  mov   cl   ,   3  
                  shl   ax   ,   cl         ;   结果     ax   =   0011_1011_0100_0000     
                  mov   ax   ,   1100_0111_0110_1000B  
                  mov   cl   ,   3  
                  shr   ax   ,   cl         ;   结果     ax   =   0001_1000_1110_1101    
  算术移位要保证符号位的不改变(逻辑左移位补0,   逻辑右移位看符号位) 
  例如:     mov   ax   ,   1100_0111_0110_1000B  
                  mov   cl   ,   3  
                  sal   ax   ,   cl          ;   结果     ax   =   0011_1011_0100_0000      
                  mov   ax   ,   1100_0111_0110_1000B  
                  mov   cl   ,   3  
                  sar   ax   ,   cl          ;   结果     ax   =   1111_1000_1110_1101   
                 mov   ax   ,   0100_0111_0110_1000B  
                  mov   cl   ,   3  
                  sar   ax   ,   cl           ;   结果     ax   =   0000_1000_1110_1101          
 

可以总结如下:

  算术左移同逻辑左移  
  算术右移移入的位用符号位填  
  逻辑右移移入的位用0填 


4.#define SQR(x) (x*x)
           inline  int  sqr(x)
{
  return x*x;
}
什么情况下结果不同
解:++i
这个知识点考察的是#define只是字符串替换作用,以及++i在表达式中使用的是其改变后的值,i++在表达式中使用的是其改变前的值

 

5.

union   DATE  
  {  
  char   a;  
  int   i[5];  
  double   b;  
  };  
  struct   date  
  {  
  int   j;  
  DATE   d;  
  float   f;  
  };  
  DATE   max;  
   
  void   main()  
  {  
  cout   <<   sizeof(   struct   date   )   <<   "/t"   <<   sizeof(max)   <<   endl;  
  }  
  用vc运行  
  为什么输出:40       24

 union   DATE  
  {  
          char   a;  
          int   i[5];  
          double   b;  
  };  
   
  ①联合就是一个结构,②它的所有成员相对于基地址的偏移量都为0,③此结构空间要大到足够容纳最“宽”的成员,④并且,其对齐方式要适合于联合中所有类型的成员。  
   
  该结构要放得下int   i[5]必须要至少占4×5=20个字节。如果没有double的话20个字节够用了,此时按4字节对齐。但是加入了double就必须考虑double的对齐方式,double是按照8字节对齐的,所以必须添加4个字节使其满足8×3=24,也就是必须也是8的倍数,这样一来就出来了24这个数字。综上所述,最终联合体的最小的size也要是所包含的所有类型的基本长度的最小公倍数才行。(这里的字节数均指winnt下的值,平台、编译器不同值也有可能不同。)  
另外对于:  
  union   DATE  
  {  
  char   a;  
  int   i[5];  
  double   b;  
  };  
  struct   date  
  {  
  int   j;  
  DATE   d;  
  float   f;  
  };  
   
  结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma   pack指定的数值和这个数据成员自身长度中,比较小的那个进行。  
  而编译器默认为:  
  #pragma   pack(8)         //可以更改在:vc6中打开工程属性页,c/c++页,选择Code   Generation分类,  
                                        在   Struct   member   alignment可以选择。  
   
   
  所以DATE的对齐方式就是以8的倍数开始的.  
   
  所以DATE的内存分存就如下:  
  jjjj****  
  dddddddd  
  dddddddd  
  dddddddd  
  bbbbbbbb  
  sizeof(date)=8+24+8=40

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值