Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;编写恐怖代码的例子还是绝妙的想法?_C++_Optimization_Syntax - Fatal编程技术网

C++ C++;编写恐怖代码的例子还是绝妙的想法?

C++ C++;编写恐怖代码的例子还是绝妙的想法?,c++,optimization,syntax,C++,Optimization,Syntax,在以前的一位雇主,我们写的是二进制信息,必须“通过电线”传送到其他计算机。每封邮件都有一个标准标题,类似于: class Header { int type; int payloadLength; }; char* Header::GetPayload() { return ((char*) &payloadLength) + sizeof(payloadLength); } 所有数据都是连续的(头,后面紧跟着数据)。我们想要得到有效载荷,因为我们有一个指向头

在以前的一位雇主,我们写的是二进制信息,必须“通过电线”传送到其他计算机。每封邮件都有一个标准标题,类似于:

class Header
{
    int type;
    int payloadLength;
};
char* Header::GetPayload()
{
    return ((char*) &payloadLength) + sizeof(payloadLength);
}
所有数据都是连续的(头,后面紧跟着数据)。我们想要得到有效载荷,因为我们有一个指向头的指针。传统上,你可能会这样说:

class Header
{
    int type;
    int payloadLength;
};
char* Header::GetPayload()
{
    return ((char*) &payloadLength) + sizeof(payloadLength);
}
甚至:

char* Header::GetPayload()
{
    return ((char*) this) + sizeof(Header);
}
这似乎有点冗长,所以我想到:

char* Header::GetPayload()
{
    return (char*) &this[1];
}
一开始它看起来相当令人不安,可能太奇怪了以至于无法使用——但非常紧凑。 关于它是辉煌的还是令人憎恶的,有很多争论

那么,哪一个是反编码犯罪,还是好的解决方案?你有过类似的权衡吗

-更新:

我们确实尝试过零大小的数组,但当时编译器发出了警告。 我们最终使用了内置技术:消息源于头。
它在实践中效果很好,但在原则上,你说的是一个消息头,这似乎有点尴尬。

我个人认为,如果有犯罪,它是在向消息头索要有效负载

但是,只要你打算这样做,“这个+1”是一个很好的方法

理由:“&this[1]”是一段通用代码,它不需要您通过挖掘类定义来完全理解,也不需要在有人更改类的名称或内容时进行修复

顺便说一句,第一个例子是真正的反人类罪。在类的末尾添加一个成员,它将失败。在课堂上移动成员,它就会失败。如果编译器填充该类,它将失败

此外,如果您要假设编译器的类/结构布局与您的数据包布局匹配,那么您应该了解所讨论的编译器是如何工作的。例如,在MSVC上,您可能想了解
#pragma pack


有多少人认为“这个+1”或“&这(1)”很难阅读或理解。有点吓人。别误会我的意思,这很聪明,但你节省了你自己一个完整的加法操作,代价是使代码更难理解和阅读。我认为这种折衷是不值得的。

我宁愿反对编码犯罪

这两种方法将生成完全相同的目标代码。第一,明确其意图。第二个是非常混乱的,唯一的优点是它节省了几个按键。(只要学学着打怪字就行了)

另外,请注意,这两种方法都不能保证有效。sizeof()对象包含用于单词对齐的填充,因此如果标题为:

class Header
{
    int type;
    int payloadLength;
    char  status;
};

您描述的两种方法的有效负载都从Header+12开始,而实际上很可能从Header+9开始。

也许您应该使用详细的方法,但用#define宏替换它?通过这种方式,您可以在键入时使用速记,但任何需要调试代码的人都可以毫无疑问地进行操作。

就我而言,他们基本上是一样的。两者都是字节杂耍的形式,这总是有风险的,但并非不可能正确。 第一种形式更易于接受和识别。 我个人会写:

char* Header::GetPayload()
{
    return ((char*) this) + sizeof(*this);
}

我认为如果标头需要“返回”未包含在其中的数据,那么从一开始就存在缺陷

既然你已经把自己放在了这些下流的理由上,我真的很喜欢你的想法

但请注意,这不是一场选美比赛。你应该找到一个完全不同的解决方案。对于您介绍的GetPayload()的所有三个版本,如果没有您的进一步解释,我将无法理解到底发生了什么。

如果它一直有效,那么它是一个优雅的解决方案

它通常在内存中工作,因为编译器将处理对齐问题,并且您可以假设负载在正确对齐的内存空间中跟随标头

我可以看到,当标题/有效负载对象“在线路上”流式传输时,这种情况就会出现,因为您使用的流式传输机制可能不关心在任何特定边界上对齐对象。因此,有效载荷可以直接跟随收割台,而无需填充,以强制其进行特定对齐


用一句话来说,优雅就是优雅。因此,只要您小心地流式处理它,它就是优雅的。

您依靠编译器以特定的方式布局类。我会将消息定义为一个结构(由我定义布局),并拥有一个封装消息并提供其接口的类。清除代码=良好代码。“可爱”代码=错误(难以维护)代码


自从我写过C++以来,已经有一段时间了,所以请原谅任何语法问题。只是想表达一下大意。

别忘了VC++可能会在类的
sizeof()
值上加上填充。由于提供的示例预期为8个字节,因此它是自动DWORD对齐的,所以应该是ok。检查


尽管如此,我同意,所提供的示例是某种程度的编码恐惧。许多Win32数据结构在跟随可变长度数据时在标头结构中包含指针占位符。一旦数据加载到内存中,这可能是引用该数据的最简单方法。MAPI结构就是这种方法的一个例子。

首先,在“反编码犯罪”和“不错的解决方案”之间有很大的距离,但我认为这更接近前者

收割台是有效载荷的保持器吗

这是这里的基本问题——头和有效负载都应该由另一个保存整个消息的对象管理,这是请求有效负载的正确位置。它将能够做到这一点,而无需指针算法或索引

有鉴于此,我倾向于第二种解决方案,因为它更清楚正在发生的事情

但我们现在的处境似乎表明
struct bla {
    int i;
    int j;
    char data[0];
}
struct header
{
    short id;
    short size;
}

struct foo
{
    header hd;
    short hit_points;
}


short get_foo_data(char *packet)
{
    return reinterpret_cast<foo*>(packet)->hit_points;
}

void handle_packet(char *packet)
{
    header *hd = reinterpret_cast<header*>(packet);
    switch(hd->id)
    {
        case FOO_PACKET_ID:
            short val = get_foo_data(packet);
        //snip
    }
}
class Header
{
    int type;
    int payloadLength;
    char payload[0];

};

char* Header::GetPayload()
{
    return payload;
}
#include <stdint.h>
#include <arpa/inet.h>

class Header {
private:
    uint32_t type;
    uint32_t payloadlength;
public:
    uint32_t getType() { return ntohl(type); }
    uint32_t getPayloadLength() { return ntohl(payloadlength); }
};

class Message {
private:
    Header head;
    char payload[1]; /* or maybe std::vector<char>: see below */
public:
    uint32_t getType() { return head.getType(); }
    uint32_t getPayloadLength() { return head.getPayloadLength(); }
    const char *getPayload() { return payload; }
};