C/C++ 微软面试经典剖析

1  分析下面的程序


struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};

struct s2
{
int i: 8;
int j: 4;
double b;
int a:3;
};

printf("sizeof(s1)= %d\n", sizeof(s1));
printf("sizeof(s2)= %d\n", sizeof(s2));

答案    16, 24

剖析:

第一个struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};
理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前总共是18位,折算过来是2字节2位的样子,由于double是8 字节的,因此要在相对0要是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字节的位置了,因此,总共是16字节。
1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:   
struct bs  
{  
unsigned a:4  
unsigned :0 /*空域*/  
unsigned b:4 /*从下一单元开始存放*/  
unsigned c:4  
}  
在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位
3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如: 
struct k  
{  
int a:1  
int :2 /*该2位不能使用*/  
int b:3  
int c:2  
};  
从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的

2 在对齐为4的情况下 分析下面程序的结果

struct BBB
{
long num;
char *name;
short int data;
char ha;
short ba[5];
}*p;
p=0x1000000;
p+0x200=____;
(Ulong)p+0x200=____;
(char*)p+0x200=____;

剖析:
假设在32位CPU上,
sizeof(long) = 4 bytes
sizeof(char *) = 4 bytes
sizeof(short int) = sizeof(short) = 2 bytes
sizeof(char) = 1 bytes

由于是4字节对齐,
sizeof(struct BBB) = sizeof(*p)
= 4 + 4 + 2 + 1 + 1/*补齐*/ + 2*5 + 2/*补齐*/ = 24 bytes (经Dev-C++验证)

p=0x1000000;
p+0x200=____;
= 0x1000000 + 0x200*24   指针加法,加出来的是指针类型的字节长度的整倍数。就是p偏移sizeof(p) *0x200.

(Ulong)p+0x200=____;
= 0x1000000 + 0x200   经过ulong后,这已经不再是指针加法,而变成一个数值加法了

(char*)p+0x200=____;
= 0x1000000 + 0x200*1  结果类型是char*,这儿的1是char的数据类型是1字节



分析一下下面程序的输出结果

#i nclude<iostream.h>
#i nclude <string.h>
#i nclude <malloc.h>
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <memory.h>
typedef struct AA
{
         int b1:5;
         int b2:2;
}AA;
void main()
{
        AA aa;
        char cc[100];
        strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
        memcpy(&aa,cc,sizeof(AA));
        cout << aa.b1 <<endl;
        cout << aa.b2 <<endl;
}

答案: -16和1
剖析:
"0 "的ascii码是0x30,表示成2进制就是00110000。 "1 "的ascii码是0x31,表示成2进制是00110001。前面当然都有有0011。注意,你做strcpy拷到cc里的是字符 '0 ', '1 ', '2 '.....不是数字0,1,2..... 

sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.
经过strcpy和memcpy后,aa的4个字节所存放的值是:
0,1,2,3的ASC码,即00110000,00110001,00110010,00110011
所以,最后一步:显示的是这4个字节的前5位,和之后的2位
分别为:10000,和01
因为int是有正负之分,所以是-16和1


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