简体   繁体   English

将struct指针转换为char *并复制

[英]Cast struct pointer to char* and copy

I have the following code 我有以下代码

struct Info { int age; char name[5]; }
char buffer[20];
Info i;
i.age = 10;
sprintf(i.name, "Case");
strncpy(buffer+5, (char*)&i, sizeof(Info));

Now I want to recover the record 现在我想要恢复记录

Info j;
strncpy((char*)&j, buffer+5, sizeof(Info));
printf("%d %s", j.age, j.name);

However this prints empty string for name. 但是,这会打印名称的空字符串。 I'm not sure what I am doing wrong. 我不确定我做错了什么。

There are two problems with your copying mechanism: 复制机制有两个问题:

  1. You're assuming that sizeof(Info) is 5. That's definitely not the case. 你假设sizeof(Info)是5.那绝对不是这样的。
  2. You're using strncpy , which is for strings. 你正在使用strncpy ,这是用于字符串的。 Info is not a string, so you need to use memcpy . Info不是字符串,因此您需要使用memcpy

The following will work: 以下将有效:

char buffer[sizeof(i)];
memcpy(buffer, &i, sizeof(i));

...

memcpy(&j, buffer, sizeof(j));

There's also another problem; 还有另一个问题; name[5] is not big enough to hold "Casey" , as that's 6 characters once you've accounted for the null terminator . name[5]不足以容纳"Casey" ,因为一旦你考虑了null终止符,就会有6个字符。

There's a few things: 有几件事:

  • You're overflowing the buffer, char name[5] can't hold "Casey" , the terminator won't fit. 你正在溢出缓冲区, char name[5]不能容纳"Casey" ,终结符将不适合。 This causes undefined behavior. 这会导致未定义的行为。
  • You're copying from &i as if that was the pointer to a string, when in fact it points at a struct whose first field is an int . 你抄袭&i ,就好像那是指向字符串的指针,而实际上它指向一个struct ,其第一场是int This won't work reliably. 这将无法可靠地工作。

There are several issues with the code you posted. 您发布的代码存在几个问题。 First, the name field of info is too short considering that "Casey" must be null terminated. 首先,考虑到“Casey”必须为空终止, infoname字段太短。

The observation you made is due to another problem. 你做的观察是由于另一个问题。 The address of j will not be aligned with its name field. j的地址不会与其name字段对齐。 There is still an int age in that place, and most likely the name field starts 4 bytes later, but this is to the discretion of your compiler. 在那个地方仍然存在一个int age ,并且很可能name字段在4个字节之后开始,但这是由编译器自行决定的。

As for recovering age , that would not work because it was never stored to the buffer. 至于恢复age ,这是行不通的,因为它从未存储到缓冲区。

What could work is, assuming that buffer is large enough, to memcpy(buffer, &i, sizeof(Info)) to store, and the first two arguments switched to reconstruct. 假设buffer足够大,可以使用memcpy(buffer, &i, sizeof(Info))来存储,前两个参数切换为重建。 Using sizeof helps here because this way you are asking the compiler how large the structure Info is given its way of layouting this structure in memory. 在这里使用sizeof会有所帮助,因为这样你就可以向编译器询问结构Info在内存中布局这个结构的方式有多大。

You do not need to use memcpy() to copy Info variables. 您不需要使用memcpy()来复制Info变量。 You can just use the assignment operator: 你可以使用赋值运算符:

Info j;
j = i;
printf("%d %s", j.age, j.name);

You can do that because Info does not contain pointer member variables, and therefore you'll get a deep copy when using the assignment operator. 您可以这样做,因为Info不包含指针成员变量,因此在使用赋值运算符时您将获得深层复制。 The same will happen if you just use the default copy constructor: 如果您只使用默认的复制构造函数,也会发生同样的情况:

Info j(i);

or: 要么:

Info j = i;

Of course as pointed out by others, you should make Info::name large enough to hold the names you intent to store in it including the '\\0' string terminator. 当然,正如其他人所指出的那样,你应该使Info::name足够大,以容纳你打算存储在其中的名称,包括'\\0'字符串终止符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM