首页 > 试题广场 >

在一个64位的操作系统中定义如下结构体以及对应的fool函数

[单选题]
在一个64位的操作系统中定义如下结构体:
struct st_task
{
    uint16_t id;
    uint32_t value;
    uint64_t timestamp;
};
同时定义fool函数如下:
void fool()
{
    st_task task = {};
    uint64_t a = 0x00010001;
    memcpy(&task, &a, sizeof(uint64_t));
    printf("%11u,%11u,%11u", task.id, task.value, task.timestamp);
}

上述fool()程序的执行结果为()


  • 1,0,0
  • 1,1,0
  • 0,1,1
  • 0,0,1
答案:A
考点:字节对齐,低地址到高地址
    因为字节对齐的原因,所以id占用4个字节,value和timestamp分别是4个字节、8个字节。虽然id占用四个字节的地址,但是只有低两位地址的数值有效(字节对齐的机制,即value存储时的地址对4(自身对齐值)求余应为0)。所以id为 0001 0001,高四位无效,所以为0001,value与timestamp分别为0.
    比如:地址从0x0000开始,id存储地址本来为0x0000-0x0001,但value存储地址要从0x0004开始,因为0x0004%4==0,所以id存储地址为0x0000-0x0003, value存储地址为0x0004-0x0007, timestamp存储地址为0x0008-0x000F. 所以id == 0x00010001,去掉高4位,id=0x0001,其余为0.
编辑于 2015-08-10 20:09:44 回复(11)
st_task:
id        value     timestamp
0000|0000|0000 0000|0000 0000 0000 0000 (physical)

a: 
0000 0000 0001 0001   (logic)
0001 0001 0000 0000   (physical)


st_task:
id        value     timestamp
0001|0001|0000 0000|0000 0000 0000 0000
1        |0        |0

发表于 2015-09-10 10:36:45 回复(0)
答案是:A

前面解释的都有些问题。
看如下:输出的是1,0,0和10001。
uint64_t占用8字节,那么a可以表示为0x0000000000010001。而在注意的是,在task是字节对齐的。所以对于前四个字节,分别是是01000100 00000000 0000000000000000,而id对应前两个字节所以是1,而value对应四个字节是00000000,后面的也是如此,也就是0100之后的0100只是起了填充的作用,所以当你打出task时会输出0x10001。
    typedef short uint16_t;
    typedef int uint32_t;
    typedef long long uint64_t;
    struct st_task
    {
        uint16_t id;
        uint32_t value;
        uint64_t timestamp;
    };
    st_task task = {};
    uint64_t a = 0x00010001;
    memcpy(&task, &a, sizeof(uint64_t));
    printf("%11u,%11u,%11u \n", task.id, task.value, task.timestamp);
    printf("0x%x\n", task);

发表于 2015-07-03 10:59:39 回复(7)
A
根据4字节对齐原则,id占用4字节,value占用4字节,timestamp占用8字节
a高位补0则为 0x 0000 0000 0001 0001
复制给结构体时:
低位4个字节复制到id --> id为1
高为4个字节复制到value --> value为0
timestamp不改变
如果8字节对齐,那么就更容易了,直接a覆盖到id上,答案还是A
编辑于 2015-03-10 14:14:22 回复(10)
首先是结构的内存对齐,所以2,3字节是padding的,value是4-7,timestamp是8-15
然后就是小端对齐,所以从a的低字节开始填入结构体的内存空间
发表于 2015-08-22 22:33:13 回复(4)
我是菜青虫,连答案都看不懂^==^
发表于 2017-01-20 10:20:43 回复(0)
答案:C
uint64_t a = 0x00010001; a是一个64位无符号数,通过内存拷贝,最高16位拷贝给task.id,为0,然后接着32位拷贝给task.valus,为1,最后16位拷贝给task.timestamp,为1
发表于 2015-01-28 11:30:30 回复(1)
1字节     uint8_t
2字节     uint16_t
4字节     uint32_t
8字节     uint64_t
发表于 2015-08-16 12:19:10 回复(0)
本题目融合了内存的存储模式:逻辑低位对应放在内存的高位地址,我们接下来要搞清楚一个地址所对应的内存大小为多少?64位机器,一个地址存放1字节的内容。对于0x0001 0001而言,它所占用的内存大小为4字节,证明00、01、00、01各自存在一个地址上,所以存放的状态为01 00 01 00。对于st_task,它包含有3个成员,成员按照高地址向低地址逐个排放,注意字节对齐!unit16_t是要占用2字节,而uint32_t占用4字节,注意此时考虑字节对齐问题,unit32_t这个成员不能紧靠uint16_t存放,要空2个字节的位置。而uint64_t是占用8个字节,可以紧靠uint32_t存放。接下来,我们看如何进行拷贝数据。高位放高位,0x0001 0001一共2字节,结果全放在了uint16_t的所占据的4字节范围内,注意虽然uint16_t占用了4字节,但受其数据类型的限制,只能有高位地址的内存。而此时高位的存放状态是0x0100 0100,只有前面的0100被使用再转换成逻辑格式位0001,即为1。而uint32、uint64压根就没见着0x0001 0001所复制过来的数据,因此它们都是0.
发表于 2021-09-03 12:07:02 回复(0)
1   uint64_t a = 0x00010001; 是16进制的,所以变成二进制是0000|0000|0000|0001|0000|0000|0000|00001
2   由于id占16为bit,计算机是小端 0000|0000|0000|00001 左边这个就给它了,右边0000|0000|0000|0001这个由于字节对齐,是在补位里面的,所以uint32_t value;  uint64_t timestamp;全是0
发表于 2021-08-21 15:29:32 回复(0)
id低地址,timestamp高地址。0x00010001为低地址正好为四个字节,对应id。而高位全为0,对应value, timestamp。
发表于 2021-05-25 13:30:10 回复(0)
http://m.blog.csdn.net/article/details?id=8510401 在结构体中,成员数据对齐满足以下规则:   a、结构体中的第一个成员的首地址也即是结构体变量的首地址。         b、结构体中的每一个成员的首地址相对于结构体的首地址的偏移量(offset)是该成员数据类型大小的整数倍。         c、结构体的总大小是最大数据类型的的整数倍 大小端: 对于0x11223344,肯定是左边大,右边小 小端是小的在低址,大端是大的在低址 小端 44332211 低址–高址 大 端 11223344 高址–低址 所以id占0,1 value占4,5,6,7 2,3作为补齐, 0x00010001不够8个字节,所以需要扩充,0000 0000 0001 0001,因为是小端,所以id为01 00,value为0000 然后输入结果%11u表示11位,id只有8位 0000 首先是结构的内存对齐,所以2,3字节是padding的,value是4-7,timestamp是8-15 然后就是小端对齐,所以从a的低字节开始填入结构体的内存空间
编辑于 2017-05-14 21:37:26 回复(0)
这题有问题,谁哪知道到底按照多少个字节对齐?别跟我说默认,如果什么条件都默认了,那还要if...else干屁呢,要条件编译干屁呢?程序员都不确定自己的代码在哪个平台跑,怎么能假定对齐标准呢?
发表于 2016-04-07 23:31:12 回复(0)
发表于 2023-05-02 00:17:21 回复(0)
在线蹲各路大神详细易懂的解答,脑子不好,上面大神的解释看不懂
发表于 2022-08-10 14:16:23 回复(0)
因为a为16进制,所以a中每个数位转化为2进制的话占4位,16进制a共8位,所以2进制为32位,结构体中元素按32位对齐,所以a只够赋值给id,而id一共有16位,按从低到高赋值,高16位(在16进制a中为高4位)就无效了,所以最终id = 0001 = 1,答案A正确
发表于 2019-04-06 18:10:55 回复(0)

考点:对齐+低地址到高地址

uint64_t占用8字节,那么a可以表示为0x0000000000010001。而在注意的是,在task是字节对齐的。所以对于前四个字节,分别是是1000
1000 00000000
0000000000000000,而id对应前两个字节所以是0x0001,而value对应四个字节是00000000
发表于 2015-08-06 21:18:57 回复(1)
我通过在64位linux下编译运行:
发表于 2024-07-18 12:04:47 回复(1)

uint64_t a =0x00010001;为64bit位, 占8字节 ,又0X表示16进制,16进制中每2位可以表示一个字节,所以a实际表示为0x0000000000010001  ;   uint16_t  占2 字节  uint32_t 占4字节  uint64_t占8字节, 又默认为小端存储模式 所以 数据低位存在地址低位 ,以16进制表示内存为 00 00 00 00 00 01 00 01 每2位为1字节,根据结构体的字节对齐,00 01 给id 即1,00 00给value 即0,后面只剩0,故 timestamp 也为0
发表于 2023-03-18 15:32:03 回复(0)
发表于 2023-01-21 19:51:56 回复(0)