首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将派生结构/意外填充导出结构字段的基部分初始化为基结构的对齐间隙

将派生结构/意外填充导出结构字段的基部分初始化为基结构的对齐间隙
EN

Stack Overflow用户
提问于 2018-10-07 13:24:06
回答 1查看 53关注 0票数 1

意外地发现,clang++7允许自己将派生结构(下面示例中的结构"B“与字段"B::u16_gap”)的字段紧密打包到基本结构的对齐间隙(结构"A")。但是示例中的函数"zero_init“期望它的输入是"A"-object,它没有使用对齐间隙,因此它可以被"memcpy”覆盖。当然,这个函数"zero_init“覆盖"B::u16_gap"-field的任何值,当应用于"B"-object时。

代码语言:javascript
复制
// compilation: clang++-7 -std=c++17 test.cpp
#include <cstdint>
#include <cstring>
#include <iostream>

struct A {
    std::uint32_t u32 = 0;
    std::uint16_t u16 = 0;
};

void zero_init(A& a) {
    static constexpr A zero = {};
    std::memcpy(&a, &zero, sizeof(A));
};

struct B: public A {
    std::uint16_t u16_gap = 0;
};

static_assert(sizeof(A) == 8);
static_assert(sizeof(B) == 8); // clang++-7 packs additional field "B::u16_gap" to the alignment gap of the A (for g++-7 it is not true)

int main() {
    B b;
    A& a = b;
    b.u16_gap = 123;
    zero_init(a);
    std::cout << b.u16_gap << std::endl; // writes "0" instead of expected "123"
}

在此代码中,不正确的部分(偏离C++17标准的“良好行为”规则)在哪里?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-07 13:39:24

就像静态断言显示的那样,A的大小是8个字节。这意味着静态“零”A-对象由8个字节的零组成。memcpy不知道类型,所以您将普通的8个字节复制到a的地址,从而覆盖u16_gap字段,该字段存储在这8个字节中,如第二个assert所示。

如果你想改变它,你只需复制6个字节,它就能工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52688933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档