【问题标题】:按属性初始化 typedef struct 问题
【发布时间】:2019-03-14 06:52:12
【问题描述】:

我定义了一个基于字节的结构,大小为 3 个字节。 (1个packetID和2个packetSize)我用sizeof函数检查了大小,效果很好:

#pragma pack(1)

typedef struct ENVIRONMENT_STRUCT{
    unsigned char packetID[1];
    unsigned char packetSize[2];
}

我像这样创建了一个变量并保留了内存:

ENVIRONMENT_STRUCT * environment_struct = new ENVIRONMENT_STRUCT();

现在我想初始化 environment_struct

问题是我试图通过属性初始化这个结构,就像这样:

*environment_struct->packetSize = 100;

但是当我检查这个值时,使用:

std::cout << "Packet Size: " << environment_struct->packetSize << endl;

结果:数据包大小:d

预期结果:数据包大小:100

如果我将使用数字,我应该使用 csdint 库定义结构吗?比如u_int8和这种类型的变量。

【问题讨论】:

  • 您真的要使用 1 个字符的数组,还是只使用一个字符可以?同样,您是否希望 packetSize 是两个字节的数组,还是可以使用 unsigned short
  • 感谢使用 unsigned char,因为我可以控制字节大小......但是通过这个例子,我明白最好使用 csdint 库来定义带有 u_int8 和 uint_16 的结构。你怎么看?
  • 当您需要控制数据的确切大小时,我认为这些会非常有效。
  • 完美,我将使用 csdint 库重新定义结构。谢谢。

标签: c++ pointers struct typedef


【解决方案1】:

当你这样做时

ENVIRONMENT_STRUCT * environment_struct = new ENVIRONMENT_STRUCT();

您将packetSize 初始化为{0, 0}。那么

*environment_struct->packetSize = 100;

将数组转换为{100, 0}。由于该数组是一个字符数组,当您将其发送到cout with

std::cout << "Packet Size: " << environment_struct->packetSize << endl;

它把它当作一个 c-string 并打印出字符串内容。由于您看到d,这意味着您的系统正在使用ascii,因为字符'd' 具有100 的整数表示。要查看 100,您需要将其转换为 int 类似

std::cout << "Packet Size: " << static_cast<int>(*environment_struct->packetSize) << endl;

请注意,由于packetSize 是一个由两个字符组成的数组,因此您实际上不能分配一个占用整个空间的值。如果你想要这个,那么你需要使用固定宽度类型,比如

typedef struct ENVIRONMENT_STRUCT{
    uint8_t packetID; // unsigned integer that is exactly 8 bits wide.  Will be a compiler error if it does not exist
    uint16_t packetSize; // unsigned integer that is exactly 16 bits wide.  Will be a compiler error if it does not exist
};

int main()
{
    ENVIRONMENT_STRUCT * environment_struct = new ENVIRONMENT_STRUCT();
    environment_struct->packetSize = 100;
    std::cout << "Packet Size: " << environment_struct->packetSize << std::endl;
}

【讨论】:

  • 谢谢 NathanOliver,这是我需要的答案。
【解决方案2】:

让我们首先考虑*environment_struct-&gt;packetSize = 100; 的作用。它将ENVIRONMENT_STRUCT::packetSize 的第一个字节设置为100。更常规的语法是:environment_struct-&gt;packetSize[0] = 100

确实没有办法以某种方式初始化结构,以使表达式std::cout &lt;&lt; environment_struct-&gt;packetSize 导致输出为 100。让我们考虑一下它的作用。 environment_struct-&gt;packetSize 是一个数组,在这种情况下它衰减为指向第一个元素的指针。插入字符流的字符指针被解释为以空字符结尾的字符串。幸运的是,您已经对environment_struct-&gt;packetSize 的第二个字节进行了值初始化,因此您的数组确实是空终止的。第一个字节的值被解释为编码字符。在您的系统编码中,d 字符恰好被编码为值 100。

如果您希望打印 environment_struct-&gt;packetSize 的第一个字节的数值,您已设置为 100,您可以使用:

std::cout << "Packet Size: " << (int)environment_struct->packetSize[0] << endl;

【讨论】:

    【解决方案3】:

    当您尝试打印字符符号而不是整数时,您会得到此结果。

    要修复它,只需根据您的需要强制转换值或将其声明为整数。

    演员表:

    std::cout << "Packet Size: " << static_cast<int>(*environment_struct->packetSize) << std::endl;
    

    【讨论】:

    • 我建议包含一些可以执行强制转换的示例代码。
    【解决方案4】:

    由于 packetSize 被声明为 char 类型,它被作为字符输出。 (字符'd'的ASCII码是100...)

    尝试将其转换为整数类型:

    std::cout << "Packet Size: " << (int)environment_struct->packetSize << endl;
    

    另外,由于您似乎希望将数字存储为 2 字节类型,您可以避免这种转换,只需将 packetSize 声明为 unsigned short。这将被cout 解释为整数类型。

    【讨论】:

    • 我声明了 unsigned char 来管理字节大小。那么,如果我将使用数字,我应该使用 u_int 还是类似的东西?
    • @Ian 现在有std::byte 代表一个字节的数据。
    • @JoseJimRin 有uint8_tuint_least8_t
    • 你生活和学习!请注意,如果 OP 想要 2 个字节来存储数字,我们应该谈论 uint16_t...
    • @appleapple 好的,我现在明白了。但是我以后会使用csdint库,因为我通过字节的控制使用了unsigned char。这是错误的。本例最好使用 u_int8 或 u_int16。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    相关资源
    最近更新 更多