c++一道假设性的面试题,求大神
struct A
{
int a;
int b;
char c;
char d;
}a;
struct B
{
int a;
int b;
char c;
char d;
char e;
}b;
初始化a、b;
a.a=1; a.b=2; a.c=3; a.d=4;
b.a=1; b.b=2; b.c=3; b.d=4; b.e=5;
假设a结构体直接复制个b成立: b = a;
问最后b.e的值是多少?
[解决办法]
b.e未知。
在32位系统中对齐到4字节边界的逻辑下,A中四个域都不需要对齐调整,但需要在d后面填充两个字节,以合吃族在A数组类型中,下一个元素依然从4字节边界开始,以保证两个int类型成员正好占据一个32位字。B也一样,需要在e后面填充一个字节。
这样,如果以memcpy的方式把A对象赋值给B对象,e对应的位置正好是A对象中的填充字节,填充字节会是什么数据,这一点很难确定。
[解决办法]
假设a结构体直接复制个b成立
……这个假设怎么成立的。
[解决办法]
b.e应该不变吧。
貌似考直接将基类对象直接赋值给派生类对象。
[解决办法]
我怎么也觉得应该是0啊……还写了个程序看了下:
#include <iostream>
using namespace std;
struct A{
int x;
int y;
char z;
char w;
}a;
struct B{
int x;
int y;
char z;
char w;
char e;
}b;
int main()
{
a.x = 1;a.y = 2;a.z = 3;a.w = 4;
b.x = 1;b.y = 2;b.z = 3;b.w = 4;b.e = 5;
int sizeA = sizeof(a);
int sizeB = sizeof(b);
cout << sizeA << endl;
cout << sizeB << endl;
return 0;
}
断点打在第24行,停下来以后看内存是这个样子的:
00401321call 0x4133f0 <__main>
00401326movl $0x1,0x474008(a.x------4B)
00401330movl $0x2,0x47400c(a.y------4B)
0040133Amovb $0x3,0x474010(a.z------1B)
00401341movb $0x4,0x474011(a.w------1B)
00401348movl $0x1,0x474014(b.x------4B)
00401352movl $0x2,0x474018(b.y------4B)
0040135Cmovb $0x3,0x47401c(b.z------1B)
00401363movb $0x4,0x47401d(b.w------1B)
0040136Amovb $0x5,0x47401e(b.e------1B)
00401371movl $0xc,0x18(%esp)
00401379movl $0xc,0x1c(%esp)
并且在win32平台下a和b的大小都是12B,a填充了两个字节:0x474012和0x474013位置,b填充一个字节:0x47401f,那么如果可以做复制操作的话,并假定这个复制是简单的内存块复制,这样应该是将a所占的内存空间覆盖到b的内存空间,从而b.e位置是0x474012的内容,
0x474012: 00 00 01 00 00 00 02 00
[解决办法]
00 00 03 04 05 00 00 00 ................
0x474022: 00 00 00 00 00 00 00 00
[解决办法]
00 00 00 00 00 00 00 00 ................
可以看到a的两个填充字节都是填充0的,所以b.e也应该变成0啊……果然我也要被面试官鄙视了么。
但是这个复制的假定并不知道到底是怎么样实现的,而且不同的平台是不是也不一定就填充0,但这样的话就不会说是有确定的值了……想不明白,同求大神解惑!
[解决办法]
填充值不一定是0
面试官2b不解释
[解决办法]
能转换么,俩不同对象,你的值是无法确定的
[解决办法]
没啥意义的假设