C++ 没有';我真的不明白

C++ 没有';我真的不明白,c++,sockets,boost-asio,C++,Sockets,Boost Asio,我有一些套接字连接代码,它使用boost::asio从套接字读取前5个字符,从中可以确定发送的字符串是否是使用zlib库压缩的。我目前正在做的项目是重写现有的一些东西,所以我把一些现有代码,使它更像C++,而不是C。然而在代码中,它有一个对 MeMCPY < /C>的调用,这对我来说似乎完全是多余的,但是如果那个调用不在那里,调用 AycCyRead < /C> >永远不会被调用,这就是我不明白的。为什么?此memcpy调用的目的是什么?为什么需要从所有指标中选择它 /*check for zl

我有一些套接字连接代码,它使用boost::asio从套接字读取前5个字符,从中可以确定发送的字符串是否是使用zlib库压缩的。我目前正在做的项目是重写现有的一些东西,所以我把一些现有代码,使它更像C++,而不是C。然而在代码中,它有一个对<代码> MeMCPY < /C>的调用,这对我来说似乎完全是多余的,但是如果那个调用不在那里,调用<代码> AycCyRead < /C> >永远不会被调用,这就是我不明白的。为什么?此
memcpy
调用的目的是什么?为什么需要从所有指标中选择它

/*check for zlib compression and then call handle_read_s which gets the rest of the data and decompresses if necessary.*/
/// buff is a vector<char>
/// tempbuff is a char[5]
void tcp_connection::handle_read(const boost::system::error_code& err, size_t bytes_transferred, endpoint_ptr ptr)
{
    unsigned long maxsz = 1024; //0xffffffff;
    size_t size = 1024;
    b_zlib = false;

    if (!err || err ==  boost::asio::error::message_size)
    {
        if (bytes_transferred >= 4)
        {
            if (tempbuff[0] == 'Z')
                b_zlib = true;

            //Remove 4 bytes & remove memcpy
            memcpy(&maxsz, &tempbuff[1], 4);   //removing this makes my code unworkable, I don't get it?
            buff.resize(maxsz);  //passing anything else here also kills it?!!
            boost::asio::async_read(socket_, boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read_s, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, ptr));
        }
    }   

}
/*检查zlib压缩,然后调用handle\u read\s获取其余数据,必要时进行解压缩*/
///buff是一个向量
///tempbuff是一个字符[5]
无效tcp\u连接::句柄\u读取(常量boost::系统::错误\u代码和错误,大小\u t字节\u传输,端点\u ptr ptr)
{
无符号长maxsz=1024;//0xffffffff;
大小\u t大小=1024;
b_zlib=假;
如果(!err | | err==boost::asio::error::message|u size)
{
如果(传输的字节数>=4)
{
if(tempbuff[0]=='Z')
b_zlib=真;
//删除4个字节并删除memcpy
memcpy(&maxsz,&tempbuff[1],4);//删除它会使我的代码无法运行,我不明白吗?
buff.resize(maxsz);//在这里传递任何东西都会杀死它?!!
boost::asio::async_read(套接字、boost::asio::buffer(buff)、boost::bind(&tcp_connection::handle_read_s、shared_from_this()、boost::asio::placeholder::error、boost::asio::placeholder::bytes_transfer、ptr));
}
}   
}

该代码基本上与以下代码相同,我假设您对其更熟悉:

maxsz = *reinterpret_cast<unsigned long*>(&tempBuff[1]);
// or possibly, depending on endianness, ...
maxsz = ntohl(*reinterpret_cast<unsigned long*>(&tempBuff[1]));
maxsz=*重新解释演员阵容(&tempBuff[1]);
//或者可能,取决于endianness。。。
maxsz=ntohl(*重新解释施法(&tempBuff[1]);

不同之处在于,以代码的方式使用
memcpy
符合标准,而使用
reinterpret\u cast
如图所示调用。我认为tempbuff的前4个字节会影响缓冲区的大小,因此它会读取前4个字节,确定缓冲区的大小,然后将缓冲区大小调整为该大小。在像DeldJARN这样的RealTytReST中执行这一操作会使它更像C++。

< p>这个代码告诉你所需的缓冲区的大小。

memcpy(&maxsz, &tempbuff[1], 4);
这段代码正在调整缓冲区的大小

buff.resize(maxsz);

memcpy
的目的是使代码不可移植, 当代码在另一个平台上编译时,会引入令人尴尬的错误 机器。它所做的是将
maxsz
设置为某个值,具体取决于 你刚刚读到的。该值是否正确取决于 机器。(如果我可以信任这些名称,还有未定义的 行为是
bytes\u传输的
等于4。并且
如果您将端口连接到
未签名的计算机,则可能是未定义的行为
long
是64位。)

根据协议的不同,您应该使用:

maxsz = static_cast<unsigned char>(tempbuff[1])
    | (static_cast<unsigned char>(tempbuff[2]) << 8)
    | (static_cast<unsigned char>(tempbuff[3]) << 16)
    | (static_cast<unsigned char>(tempbuff[4]) << 24);
,而不是
=
(或者
>=5
)。或者名字不应该是 传输的字节数
。您的代码访问所有五个字节的数据
tempbuff
。(就此而言,我怀疑如果
bytes\u传输的
不完全是5,事情会搞砸的。)

但是我问为什么memcpy应该在那里?为什么没有它就不能工作?@Tony The Tiger:调用
memcpy
设置
maxsz
的正确值;为什么您会认为这是可选的或不必要的?我可以使用std::copy执行相同的操作吗?除了在非常有限的情况下,硬件恰好使用线路上的确切格式,否则这两种方法都不适用。这种情况很少发生:大多数协议都是big-endian协议;最常见的硬件是little endian。而且
无符号长
很可能是8个字节。@Tony The Tiger:是的,我相信以下是符合技术标准的:
char*maxszbuf=static_cast(static_cast(&maxsz));std::copy(&tempBuff[1],&tempBuff[1+sizeof(无符号长)],maxszbuf) @达尼:我的文章的要点是,使用<代码> RealTytCase看起来更像C++,但实际上是非法的。使用<代码> MycPy < /代码>这里实际上是正确的事情。“达尼,你应该仔细重读Idjjn的答案,并考虑修改你的答案……James Kanze:据我所知,用<代码> MycPy < /Case>以这种方式定义了行为,不同于<代码> RealTytCase。(除了依赖于
sizeof(unsigned long)
being
4
)的代码之外,@James Kanze:《C++03标准》的§5.2.10/7特别指出使用
重新解释
的结果是“未指定的”,而§3.9/2特别允许并保证使用
memcpy
。关于取决于
sizeof(unsigned long)
的值,不,这不是最好的主意,但这绝不意味着使用
memcpy的部分失败;这只是一种像
uint32\u t
+Boost.Endian这样的东西被担保的情况,而不是裸
unsigned long
。另一方面,在现代MSVC和GCC上,即使对于x64,
sizeof(unsigned long)
也是
4
。@ildjarn等式中有两个“变量”:在他的平台上表示一个
unsigned long
,以及他试图在文件中读取的整数的表示。如果他知道除了在Windows上之外,代码永远不会被使用,那么他就知道内部格式。如果这与文档格式完全一致,他可以通过
reinterpret\u cast
(因为无论您如何解释标准,它都与MSVC一起工作)或
memcpy
。不过,我只是希望他的水晶球能正常工作。谢谢你的输入,代码不可移植?为什么会有人这样做?协议是TCP。和其他人一样
maxsz = (static_cast<unsigned char>(tempbuff[1]) << 24)
    | (static_cast<unsigned char>(tempbuff[2]) << 16)
    | (static_cast<unsigned char>(tempbuff[3]) << 8)
    | static_cast<unsigned char>(tempbuff[4]);
if ( bytes_transferred > 4 )