您的位置:首页 > 职场人生

内存对齐相关面试题

2018-01-14 20:21 169 查看

题目一

#pragma pack (4)
unsigned short* pucchararray[10][10];
typedef union unRec
{
unsigned long L1;
unsigned short S2[7];
unsigned char C3;
}REC_S;
REC_S stmax, *pstmax;
int main()
{

printf("%d\n", sizeof(pucchararray));
printf("%d\n", sizeof(stmax));
printf("%d\n", sizeof(pstmax));
printf("%d\n", sizeof(*pstmax));

system("pause");
return 0;
}


首先题目是考察联合体的内存对齐,联合体的内存存放是共用一段连续的内存空间。所以联合体的大小至少得是最大成员的大小,由于内存对齐所以联合体的大小必须是最大对齐数的整数倍。

本题中第一个指针数组,是一个10*10大小的数组每一个元素都是指针,所以是400.

第二个stmax是一个结构体变量,所以他的大小就是结构体的大小即16.

第三个pstmax是一个结构体指针,为4个字节大小。

第四个*pstmax,对该结构体指针解引用,得到该结构体的大小,16.

题目二

3.

struct BBB
{
long A1;
char A2;
char A3;
long A4;
long A5;
}*p;
int main()
{
p = (struct BBB*)0x100000;
printf("%d\n", sizeof(struct BBB));
printf("%#x\n", p + 0x1);
printf("%#x\n",(unsigned long) p + 0x1);
printf("%#x\n",(unsigned long *) p + 0x1);
printf("%#x\n", (char *)p + 0x1);
system("pause");
return 0;
}


本题目考察了结构体的内存对齐及对指针的运算(默认4字节对齐)。首先先求出该结构体的大小。

默认第一个变量对齐,占4字节,第二三个变量可以直接存放,各占1字节,第四个变量要偏移到偏移量为8处,占4字节,第五个变量此时已对齐,占4字节。此时该结构体大小为16,并且结构体大小要是最大对齐数的整数倍,即是4的整数倍,仍是16.

所以该题目中设置了一个结构体指针,并将该指针的指向改为0x100000.

p + 0x1:对指针+1,是加上其指向类型的大小,所以加16,16进制表示为:0x1000010.

(unsigned long) p + 0x1:将指针强转为无符号长整形,对其加1,就是+1,即0x100001.

(unsigned long *) p + 0x1:将指针强转为无符号整形指针类型,对指针加1,仍然是加上其所指向类型的大小,long的大小4,即0x100004.

(char *)p + 0x1:将指针强转为字符指针类型,对指针加1,加上其所指类型的大小,就是1,即0x100001.

结果如图所示:



题目三

struct AAA
{
//位段不用对齐
unsigned char c1 : 1;
unsigned char c2 : 2;
unsigned char c3 : 6;
unsigned char c4 : 4;
unsigned char c5;
unsigned char c6 : 4;
unsigned char c7;
};
int main()
{
printf("%d\n", sizeof(struct AAA));

system("pause");
return 0;
}


位段在内存中的存储是按照比特位存储,当该申请类型的上一个字节的比特位够存时可以直接存入,不够时就要重新开辟新的字节。并且,最值得注意的一点,位段不需要对齐。

这道题目用一张图可以来说明他的内存存储。



题目四

int main()
{
unsigned char uc[4];
struct PIM
{
unsigned char c1;
unsigned char data0 : 1;
unsigned char data1 : 2;
unsigned char data2 : 3;
}*pst;
pst = (struct PIM*)uc;
memset(uc, 0, 4);
pst->c1 = 2;
pst->data0 = 3;
pst->data1 = 4;
pst->data2 = 5;
printf("%02x %02x %02x %02x", uc[0], uc[1], uc[2], uc[3]);
system("pause");
return 0;
}


本题仍然考察了位段,位段都是按照比特位存储的,所以在赋值是也是按照比特位赋值。

用下图来解释:



所以答案为:02 29 00 00

题目五

#pragma pack(4)
union AAA
{
struct
{
char c1;
short s1;
char c2;
}half;
short s2;
}number;
struct BBB
{
char c1;
short s1;
char c2;
short s2;
}half;
struct CCC
{
struct
{
char c1;
short s1;
char c2;
}half;
long l1;
};
int main()
{
printf("%d\n", sizeof(union AAA));
printf("%d\n", sizeof(struct BBB));
printf("%d\n", sizeof(struct CCC));

system("pause");
return 0;
}


本题考查了联合体与结构体的内存对齐,以及结构体嵌套结构体的情况下,结构体的内存对齐。

结果如下图所示:



在做有关于内存对齐的题目时,首先要判别清楚是结构体联合体还是位段,因为结构体和联合体需要对齐,位段不需要对齐。并且他们的存储也各有不同,分别的规则要熟记并熟练,遇到问题时,一步一步分析清楚就好了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: