我有一个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
之后启动{ {1}}。 执行以下操作会导致未定义的行为吗?假设从未使用过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
的实例之外我还想要其他内容。
答案 0 :(得分:1)
如果您避免任何与对齐相关的问题,您的代码将属于标准作者可能期望质量实现有效处理的程序类别,但标准的N1570 6.5p7部分将允许实现处理以任意方式。请注意C标准的编写方式,即使是:
struct foo {int x;} s = {0};
s.x = 1;
属于同一类别,因为标准没有描述任何类别
可以使用类型int
的左值来影响对象的情况
类型为struct foo
,它的左值定义也不包含左值可能具有int
类型但与其他类型有6.5p7关联的想法。
没有理由认为任何 quality 编译器在识别将T1*
转换为T2*
并将其传递给作用于T2*
可能会访问T1*
类型的对象。在没有-fno-strict-aliasing
标志的情况下,gcc或clang故意对这种可能性视而不见,但使用该标志会使它们像质量编译器一样。
答案 1 :(得分:0)
只要您的函数f没有处理x4和x5,那么您可以安全地将结构复制到带有修剪长度的unsigned char数组并将其传递给function.Sample程序可以是这样的:
#include <iostream>
#include <memory.h>
struct s {
double x1;
float x2;
long long x3;
int x4;
int x5;
};
struct s_trimmed {
double x1;
float x2;
long long x3;
};
void f(s* x)
{
std::cout<<x->x1<<std::endl;
std::cout<<x->x2<<std::endl;
std::cout<<x->x3<<std::endl;
}
int main() {
size_t nums = 2;
unsigned char *mem = new unsigned char[nums*sizeof(s_trimmed)];
unsigned int start = 0;
for(int i=0;i<nums;i++)
{
s* s_obj = new s;
s_obj->x1 = 10.5;
s_obj->x2 = 89.98;
s_obj->x3=28765;
s_obj->x4=1;
s_obj->x5=5;
memcpy(mem+start,s_obj,sizeof(s_trimmed));
start = start + sizeof(s_trimmed);
delete s_obj;
s_obj = nullptr;
}
start = 0;
for(int i=0;i<nums;i++)
{
unsigned char *memf = new unsigned char[sizeof(s_trimmed)];
memcpy(memf,mem+start,sizeof(s_trimmed));
f((s*)memf);
}
delete[] mem;
mem=nullptr;
return 0;
}