2012-05-10 29 views
0

我有以下两种结构。我需要使用memcpyoffsetofd, e, fsource复制到destination。我怎样才能做到这一点?如何使用'offsetof'在不同结构之间执行'memcpy'?

struct source 
{ 
    int a; 
    int b; 
    int c; 
    int d; 
    int e; 
    int f; 
}; 

struct destination 
{ 
    int d; 
    int e; 
    int f; 
}; 
+3

让我们了解您已经完成的工作。否则,人们会怀疑你试图让他们为你做功课。 – janneb

+0

你为什么要使用memcpy - 这是关于struct packing的作业问题吗? –

+0

如果这是家庭作业,请您添加作业标签吗?谢谢。 – octopusgrabbus

回答

4

一般情况下,你不能可靠地做到这一点使用memcpy,因为编译器允许两种结构不同。因此,执行部分复制的最安全方法是单独分配三个字段。

然而,由于编译器只具有不同的对齐要求,在特定情况下成员之间插入填充你可以使用memcpy这样的:

struct source s {1,2,3,4,5,6}; 
struct destination d = {100, 200, 300}; 
memcpy(&d, ((char*)(&s))+offsetof(struct source,d), offsetof(struct source,f)-offsetof(struct source,d)+sizeof(int)); 

destinationd偏移保证是零,因为它是结构的最初成员。由于成员d,ef具有相同的对齐要求,所以填充(如果有的话)将会在struct destination之后以及在struct source之前或之后跟随它们。

需要转换为char*,因为偏移量以字节表示。

表达

offsetof(struct source,f)-offsetof(struct source,d)+sizeof(int) 

df(含)之间的游程的长度。请注意,使用sizeof(struct destination)是不安全的,因为它可能在末尾有填充,而struct source中不存在填充,导致读取通过分配的内存。

+1

虽然这项任务是必需的,但在这两种情况下,使用'offsetof'都会适得其反。 '((char *)(&s))+ offsetof(struct source,d)'可以是&s.d',并且'offsetof(struct source,f)-offsetof(struct source,d)'可以是'(char *)&s.f - (char *)&s.d'。 –

+0

@SteveJessop绝对! '&s.d'比使用'offsetof'要干净得多。 – dasblinkenlight

+0

我不知道标记是否会正确地进行传递,但将某个'offsetof'扔进某处无害;-)正常情况下'offsetof'是用于你没有结构的实例进行操作的地方(例如静态地断言你的结构符合一些字节对字节的规范,比如文件格式或互联网协议),或者你想抽象出字段的名称(例如,你想要参数化你在哪个字段上看的访问者)每个对象访问)。 –

0

正如“dasblinkenlight”所说,由于可能的填充,这不能由memcpy可靠地完成。 然而,你可能做这样的事情:

struct Part1 
{ 
    int a; 
    int b; 
    int c; 
}; 

struct Part2 
{ 
    int d; 
    int e; 
    int f; 
}; 

struct source 
{ 
    struct Part1 p1; 
    struct Part2 p2; 
}; 

struct destination 
{ 
    struct Part2 p2; 
}; 

// ... 
src.p2 = dst.p2; 
+4

C没有继承。 – interjay

+0

@interjay:我已经删除了继承。现在它是一个成员(二进制级别相同) – valdo

0

对于这种情况,你也可以使用int指针的源和目标结构,然后在指定目标指针值,同时降低源和目的地INT指针。

代码的片段如下: -

struct destination * my_copy (struct source *pfSrc, struct destination *pfDes) 
{ 
    int *pSrc = (int *)pfSrc; 
    int *pDes = (int *)pfDes; 
    pSrc += (sizeof (struct source)/sizeof (int)) - 1; 
    pDes += (sizeof (struct destination)/sizeof (int)) - 1; 
    do 
    { 
    *pDes = *pSrc; 
    pSrc--; 
    }while (pDes-- != (int *)pfDes); 
return pfDes; 
}