C/C++ 微软面试题剖析

来源:互联网 发布:淘宝客招募贴怎么写 编辑:程序博客网 时间:2024/05/22 01:04

来源: 本文主要参考书籍C_c++语言面试宝典(保证你通过面试)(无答案剖析)转载请标明出处(尊重原创,谢谢!)

结构与联合有和区别?

(1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻,联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。 
 (2). 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。

关于“联合”的题目的输出

#i nclude <stdio.h>union{int i;char x[2];}a;void main(){a.x[0] = 10; a.x[1] = 1;printf("%d",a.i);}
答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)
剖析:
公用体公用一个内存区域sizeof(a)为共用体成员中长度最长的成员的size。即iint:             (|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|)char x[2] :                                                     (|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|)                  ^                                                                                                   ^               高地址                                                   低地址分析:a.x[0] = 10 ========================>                          (|0|0|0|0|1|0|1|0|)a.x[1] = 1   ======================>     (|0|0|0|0|0|0|0|1|)公用体公用sizeof(int)长度即4字节32为,则赋值后共用体内存为a:              (|0|0|0|0|0|0|0|0|)(|0|0|0|0|0|0|0|0|)(|0|0|0|0|0|0|0|1|)(|0|0|0|0|1|0|1|0|)a.i 为4字节整型则 i = 2^8 + 2^3 + 2^1 = 256 + 8 + 2 = 266

union这种类型,就是内部的变量共同使用一块空间,按照size大的分配int i 占4个字节char x[2] 占2个,所以一共分配了4个字节可以使用sizeof(a) 来看下它的总大小一共4个字节的内存,对应x来说相当于占用了低2个字节,而给x赋值的1,和10,就存在个位和十位上了(十六进制)


main(){union{ /*定义一个联合*/int i;struct{ /*在联合中定义一个结构*/char first;char second;}half;}number;number.i=0x4241; /*联合成员赋值*/printf("%c%c\n", number.half.first, mumber.half.second);number.half.first='a'; /*联合中结构成员赋值*/number.half.second='b';printf("%x\n", number.i);getch();}

答案: AB (0x41对应'A',是低位;Ox42对应'B',是高位) 

6261 (number.i和number.half共用一块地址空间)


剖析 :

union的成员是共用内存的union{ int i; struct{ char first; char second;}half;}number; number.i=0x4241;



在这里i 和 half结构是共用内存number.i=0x4241给i赋值后,内存中以二进制存储0100 0010 0100 0001
按顺序对应到结构中
halt.first=01000010   转换成10进制就是66(字母A的asc码)
halt.second=01000001 转换成10进制是65   (字母B的asc码)
所以输出后就是 AB


-------------------------------6261 (number.i和number.half共用一块地址空间)---------------------------------------------------

当然后头又给first和second赋值位"a"和"b",这样会把16位空间弄成是:
01100001 01100010 


然后用
printf("%x\n", number.i);
就是把16位看成整数,记住高地位反过来
(01100010 01100001)二进制 =   (0X6261)16进制
所以结果就是:0x6261.

3 请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1

int checkCPU(){ {  union w  {    int a;   char b;  } c;  c.a = 1;  return (c.b == 1); }} 

剖析:

嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 存放内容 0x4000 0x34 0x4001 0x12
  而在Big-endian模式CPU内存中的存放方式则为:

内存地址 存放内容 0x4000 0x12 0x4001 0x34
  32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 存放内容 0x4000 0x78 0x4001 0x56 0x4002 0x34 0x4003 0x12
  而在Big-endian模式CPU内存中的存放方式则为:

内存地址 存放内容 0x4000 0x12 0x4001 0x34 0x4002 0x56 0x4003 0x78
  联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。


4 写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)

int Sum( int n ){  return ( (long)1 + n) * n / 2;  //或return (1l + n) * n / 2;} 

剖析:
 
  对于这个题,只能说,也许最简单的答案就是最好的答案。下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return ( 1 l + n ) * n / 2相比!

int Sum( int n ){ long sum = 0; for( int i=1; i<=n; i++ ) {  sum += i; } return sum;} 




3 0
原创粉丝点击