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

来源: 本文主要参考书籍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。即i int: (|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|)(|_|_|_|_|_|_|_|_|) 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;
} 




你可能感兴趣的:(C/C++ 微软面试题剖析)