【发布时间】:2018-10-28 10:50:08
【问题描述】:
我有一个 C 库(我在 C++ 中使用它),它定义了一个结构和一个对其进行操作的函数。
struct s {
type1 x1;
type2 x2;
type3 x3;
type4 x4;
type5 x5;
};
void f(s* x);
我知道f 不会做任何涉及s::x4 或s::x5 的事情。由于它们对我的目的都没有用,而且我有很多s 的实例,我想将它们分配到一个数组中,以便将它们打包以便s[n+1] 在s[n].x3 之后立即开始。 执行以下类似操作会导致未定义的行为吗?假设从未使用过 x4 和 x5。
struct s_trimmed {
type1 x1;
type2 x2;
type3 x3;
};
size_t num_s = 1000;
char *mem = new char[stuff_before + num_s*sizeof(s_trimmed) + stuff_after];
for (size_t i=0; i<nums; ++i)
f((s*)(mem + stuff_before + i*sizeof(s_trimmed)));
mem 是一个char 数组,因为它只是一块内存,除了s 的实例之外,我还希望其中包含其他内容。
【问题讨论】:
-
显示的代码看起来并没有那么糟糕。尽管与
stuff_before相关的所有内容都有些可疑。但是您可能会将它与库实现的函数并行使用。请相应地扩展您的示例。 -
你没有创建任何
s,使用的数组就是UB。它会起作用吗?可能,如果类型都是微不足道的 -
@Yunnosch 是的,我会将它与库实现的函数一起使用。
f应该代表他们。我只展示了一个简洁的。我明确展示了s的多个成员,以防有人建议对齐可能是一个问题。x4和x5仅用于特殊的角落案例。大多数 C 库都不关心它们。 -
@PasserBy:(不幸的是)这是一个见仁见智的问题。如果 C 函数实际上是
init_1_3(s* x)并写入x->x1到x->x3,则它不是 C 端的 UB,并且为了互操作性,它也必须由 C++ 定义。现在确实有一个普遍的说法,即您不能通过写入未初始化的内存来创建 C++ 对象,但也有人声称 C 和 C++ 仍然是可互操作的。两者不可能同时为真。而实际的编译器选择第二种解释。 -
@MSalters 有关于here 的完整讨论。无论如何,由于没有足够的存储空间来存储所有
s,因此它们不存在是毫无疑问的。如果它们确实存在,您认为(*s)(mem + stuff_before)[0].x4应该是什么意思?
标签: c++ c memory-management undefined-behavior