急急急!请教memcpy 为什么会少了一个字节??

时间:2023-01-11 18:45:16
C++小白,请教高手!

#pragma pack(1)
struct testpack{
char chain;
WORD serial;
DWORD serialnumber;
};
#pragma pack()

       char cbuffer[200];
testpack * mypack = new testpack();
mypack->chain = 'C';
mypack->serial = 0;
mypack->serialnumber = 12288;
内存中testpack本来是 0x43  0x0000 0x00003000

memset(cbuffer, 0x00, 200);
memcpy(cbuffer, mypack,7 );
内存copy之后为什么是 0x430000003000   少了一个字节了!求解!

18 个解决方案

#1


早上起来先顶一个,坐等高手解答。 急急急!请教memcpy 为什么会少了一个字节??

#2


你数错了吧,无图无真相

#3


DWORD 里面是反着存储的应该是00 30 00 00

#4


其实这个问题是我在做socket连接时候发送出现的,因为send要转换成char发送,只要将结构体memcpy到char缓冲区就会出现这个问题。继续求教高手解答。

#5


应该是你自己数错了。

struct结构体,按照对齐原则,0x43之后应该会多出一个字节,我估计你没算进去,否则你应该是
memcpy(cbuffer, mypack,8 );

#6


因为你要用socket传输,建议你在给struct实例赋值的时候,先对其做初始化。我的测试代码如下:

struct testpack{
char chain;
WORD serial;
DWORD serialnumber;
};

printf("size:%d,%d,%d,%d\n", sizeof(char), sizeof(WORD),sizeof(DWORD), sizeof(testpack));
char cbuffer[200];
testpack * mypack1 = new testpack();
memset(mypack1, 0x00, sizeof(testpack));
mypack1->chain = 'C';
mypack1->serial = 0;
mypack1->serialnumber = 12288;
//内存中testpack本来是 0x43  0x0000 0x00003000

testpack* mypack2 = new testpack();
memset(cbuffer, 0x00, 200);
memcpy(cbuffer, mypack1, 8);
memcpy(mypack2, cbuffer, 8);
delete mypack1;
delete mypack2;

#7


最后我再说一句:

你直接将一个struct通过socket发送出去,难道你在接收方再copy给同样地struct?这样做可不是什么好办法。

我的建议是,就算你在接收端要恢复成struct,也应该自定义一套规则,通过json字符串格式,进行序列化和反序列化。

#8


c++一般是小字节序,DWORD的12288的十六进制是0x00003000,但在内存中因小字节序低字节在低地址高字节在高地址,所以实际存储的字节顺序是00300000,刚好反过来的;WORD serial也是如此,只不过因为值是0看不出反过来了而已。
所以最终拷贝的是0x43000000300000,没有少字节。

#9


计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
急急急!请教memcpy 为什么会少了一个字节??多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他! 急急急!请教memcpy 为什么会少了一个字节??

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。

#10


memcpy(cbuffer, mypack,sizeof(testpack) )

你那样子的做法根本不通用,而且你还字节对其之类的呢

#11


这不是字节对齐的问题,结构定义已经明确1字节对齐,3楼是正解
我觉得问题应该出在传输过程了,少发或者少接

#12


引用 11 楼 cutmelon 的回复:
这不是字节对齐的问题,结构定义已经明确1字节对齐,3楼是正解
我觉得问题应该出在传输过程了,少发或者少接

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
http://bbs.csdn.net/topics/380167545

建议楼主学会使用抓包软件比如wireshark

#13


之前我居然丢掉了#pragma pack……重新测试了下,以'-'作为结束标志,重新截了俩图:
急急急!请教memcpy 为什么会少了一个字节??

急急急!请教memcpy 为什么会少了一个字节??

#14


再上两张图,证明3楼确实是对的……我以前居然没注意到这个问题。

急急急!请教memcpy 为什么会少了一个字节??

急急急!请教memcpy 为什么会少了一个字节??

#15


老赵,我暴露出我是菜鸟的事实了,咋办?我们把CSDN黑了吧?

引用 12 楼 zhao4zhong1 的回复:
Quote: 引用 11 楼 cutmelon 的回复:

这不是字节对齐的问题,结构定义已经明确1字节对齐,3楼是正解
我觉得问题应该出在传输过程了,少发或者少接

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
http://bbs.csdn.net/topics/380167545

建议楼主学会使用抓包软件比如wireshark

#16


人无完人;完人不是人,是AlphaGo! 急急急!请教memcpy 为什么会少了一个字节??

#17


ALphaGo不是人……
引用 16 楼 zhao4zhong1 的回复:
人无完人;完人不是人,是AlphaGo! 急急急!请教memcpy 为什么会少了一个字节??

#18


struct结构的问题。

#1


早上起来先顶一个,坐等高手解答。 急急急!请教memcpy 为什么会少了一个字节??

#2


你数错了吧,无图无真相

#3


DWORD 里面是反着存储的应该是00 30 00 00

#4


其实这个问题是我在做socket连接时候发送出现的,因为send要转换成char发送,只要将结构体memcpy到char缓冲区就会出现这个问题。继续求教高手解答。

#5


应该是你自己数错了。

struct结构体,按照对齐原则,0x43之后应该会多出一个字节,我估计你没算进去,否则你应该是
memcpy(cbuffer, mypack,8 );

#6


因为你要用socket传输,建议你在给struct实例赋值的时候,先对其做初始化。我的测试代码如下:

struct testpack{
char chain;
WORD serial;
DWORD serialnumber;
};

printf("size:%d,%d,%d,%d\n", sizeof(char), sizeof(WORD),sizeof(DWORD), sizeof(testpack));
char cbuffer[200];
testpack * mypack1 = new testpack();
memset(mypack1, 0x00, sizeof(testpack));
mypack1->chain = 'C';
mypack1->serial = 0;
mypack1->serialnumber = 12288;
//内存中testpack本来是 0x43  0x0000 0x00003000

testpack* mypack2 = new testpack();
memset(cbuffer, 0x00, 200);
memcpy(cbuffer, mypack1, 8);
memcpy(mypack2, cbuffer, 8);
delete mypack1;
delete mypack2;

#7


最后我再说一句:

你直接将一个struct通过socket发送出去,难道你在接收方再copy给同样地struct?这样做可不是什么好办法。

我的建议是,就算你在接收端要恢复成struct,也应该自定义一套规则,通过json字符串格式,进行序列化和反序列化。

#8


c++一般是小字节序,DWORD的12288的十六进制是0x00003000,但在内存中因小字节序低字节在低地址高字节在高地址,所以实际存储的字节顺序是00300000,刚好反过来的;WORD serial也是如此,只不过因为值是0看不出反过来了而已。
所以最终拷贝的是0x43000000300000,没有少字节。

#9


计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

对学习编程者的忠告:
急急急!请教memcpy 为什么会少了一个字节??多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他! 急急急!请教memcpy 为什么会少了一个字节??

VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。

#10


memcpy(cbuffer, mypack,sizeof(testpack) )

你那样子的做法根本不通用,而且你还字节对其之类的呢

#11


这不是字节对齐的问题,结构定义已经明确1字节对齐,3楼是正解
我觉得问题应该出在传输过程了,少发或者少接

#12


引用 11 楼 cutmelon 的回复:
这不是字节对齐的问题,结构定义已经明确1字节对齐,3楼是正解
我觉得问题应该出在传输过程了,少发或者少接

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
http://bbs.csdn.net/topics/380167545

建议楼主学会使用抓包软件比如wireshark

#13


之前我居然丢掉了#pragma pack……重新测试了下,以'-'作为结束标志,重新截了俩图:
急急急!请教memcpy 为什么会少了一个字节??

急急急!请教memcpy 为什么会少了一个字节??

#14


再上两张图,证明3楼确实是对的……我以前居然没注意到这个问题。

急急急!请教memcpy 为什么会少了一个字节??

急急急!请教memcpy 为什么会少了一个字节??

#15


老赵,我暴露出我是菜鸟的事实了,咋办?我们把CSDN黑了吧?

引用 12 楼 zhao4zhong1 的回复:
Quote: 引用 11 楼 cutmelon 的回复:

这不是字节对齐的问题,结构定义已经明确1字节对齐,3楼是正解
我觉得问题应该出在传输过程了,少发或者少接

不知道有多少前人掉在TCP Socket
send(人多)send(病少)send(财富)
recv(人多病)recv(少财富)
陷阱里面啊!
http://bbs.csdn.net/topics/380167545

建议楼主学会使用抓包软件比如wireshark

#16


人无完人;完人不是人,是AlphaGo! 急急急!请教memcpy 为什么会少了一个字节??

#17


ALphaGo不是人……
引用 16 楼 zhao4zhong1 的回复:
人无完人;完人不是人,是AlphaGo! 急急急!请教memcpy 为什么会少了一个字节??

#18


struct结构的问题。