【问题标题】:Is there a shorter way to initialize a QByteArray?有没有更短的方法来初始化 QByteArray?
【发布时间】:2016-07-19 13:09:36
【问题描述】:

在我的程序中,我经常使用串行通信,因此经常使用QByteArray

我想知道是否有比以下更短的方法来初始化具有特定字节的QByteArray

const char test_data[] = {
    static_cast<char>(0xB1), static_cast<char>(0xB2),
    0x5, static_cast<char>(0xFF),
    static_cast<char>(0xEE), static_cast<char>(0xEE),
    static_cast<char>(0x0)}; // Note QByteArray should be able to hold 0 byte
const QCanBusFrame frame = QCanBusFrame(0xA1, QByteArray(test_data));

static_cast&lt;char&gt; 是必需的,因为否则 C++11 会给出关于缩小的错误,因为 0x7F 到 0xFF 的范围大于 char 可以容纳的范围——但 charQByteArray 构造函数要求。

这是正在使用的QByteArray 构造函数:

QByteArray::QByteArray(const char *data, int size = -1)

【问题讨论】:

  • 当您将test_data 声明为无符号字符数组 (unsigned char*) 然后将其转换为字符数组 (char*) 时会发生什么?
  • @OnurA 您确定需要使用星号吗?初始化 test_data 的行抛出“从 'int' 到 'const unsigned char* 的无效转换”
  • 您可以轻松创建一个函数,该函数使用您想要的参数创建QByteArray
  • 你的任何字节值可以是 0x00 - 如果不是,你可以使用带有字符串文字的 const char* 构造函数
  • @Jimmy 你说得对,可以将 "\x01\xB2\xB4" 传递给构造函数,但使用整数要好得多(你可以使用常量名等) .不过我应该可以有一个“0”字节......

标签: c++ qt c++11 qbytearray qt5.6


【解决方案1】:

简单有效:

QByteArray b = QByteArrayLiteral("\x12\x00\xa4\x42\x51\x00\x00\x99");

【讨论】:

  • 嗯,我在任何地方都没有看到 QByteArrayLiteral 记录,但老天说它比传递给 QByteArray 的完全相同的参数效果更好,因为“\x00”不被视为字符串终止符. QByteArray 也可以达到同样的效果,但您必须传递正确的 size 参数。不错的解决方案,谢谢:)
  • @DBedrenko 这只是一个宏:doc.qt.io/qt-5/qbytearray.html#QByteArrayLiteral
  • 我想知道 documented那个...
  • 仅从 Qt5 开始出现
  • 任何其他主要版本的 Qt 已达到 EOL。
【解决方案2】:

作为QByteArrayLiteral 的替代品,如果您愿意,您可以自己滚动:

#include <QByteArray>

template <int N> QByteArray arrayFromLiteral(const char (&data)[N]) {
   return QByteArray::fromRawData(data, N-1);
}

int main() {
   const auto arr = arrayFromLiteral("\xB1\xB2\0\1");
   Q_ASSERT(arr.size() == 4);
   Q_ASSERT(arr[0] == (char)0xB1);
   Q_ASSERT(arr[1] == (char)0xB2);
   Q_ASSERT(arr[2] == (char)0x00);
   Q_ASSERT(arr[3] == (char)0x01);
}

【讨论】:

    【解决方案3】:

    可能工作缓慢:

    QByteArray ba = QByteArray::fromHex(QVariant("B1B2FFEEEE00").toByteArray());
    

    【讨论】:

      【解决方案4】:

      受到上述答案的启发,我终于想到了:

      const quint8 testData[] {0xB1, 0x00, 0xB2, 0x00};
      const QCanBusFrame cFrame = QCanBusFrame(
          0xA1, QByteArray(reinterpret_cast<const char*>(testData), sizeof(testData)));
      

      在使用串行通信时,我更喜欢将字节作为字节数而不是文字字符。

      在讨论了##c++ 之后,我被告知reinterpret_cast 在这种情况下是合适的。

      【讨论】:

        【解决方案5】:

        像这样:

        const unsigned char str[] = {0xff, 0xed, 0xba, 0xd1};
        QByteArray ba(reinterpret_cast<const char*>(&str[0]),std::extent<decltype(str)>::value);
        

        现在 QByteArray 构造函数看起来很奇怪,但字节序列很清晰。您还可以将终止 0 字节添加到数组中,而不是使用 std::extent,但通常您可以在序列中间添加零字节。

        【讨论】:

        • 只是出于好奇,您能解释一下为什么需要 reinterpret_cast 和 std::extent 吗?
        • 我喜欢 reinterpret_cast(C++ 风格,而不是 C)。而不是范围,只需使用 sizeof(str)...
        • 你不能只转换 str 而不是 &str[0] (我觉得很难看)?至少 GCC 接受...
        【解决方案6】:

        您是否尝试过以下方法:

        const unsigned char test_data[] = {
            static_cast<char>(0xB1), static_cast<char>(0xB2),
            0x5, static_cast<char>(0xFF),
            static_cast<char>(0xEE), static_cast<char>(0xEE),
            static_cast<char>(0xB3)};
        const QCanBusFrame frame = QCanBusFrame(0xA1, QByteArray((char*)test_data));
        

        您正在使用构造函数:QByteArray::QByteArray(const char *data, int size = -1)

        如果 size 为负数,则假定 data 指向一个以 nul 结尾的字符串,并且它的长度是动态确定的。终止的 nul 字符不被视为字节数组的一部分。

        【讨论】:

        • 我刚试了一下,编译成功。它可以在没有所有 static_cast 的情况下工作(您的解决方案的全部好处是不需要这些演员表)。我不确定使用 0 字节应该注意什么:我也需要能够使用 0 字节。
        • 您绝对需要致电QByteArray((char*) test_data, sizeof(test_data));!单个参数 ctor(或 size == -1)将尝试将数据复制为正常的 c-string,它必须以 null 终止!
        • 可能如果中间有一个 0x00,它会将其检测为 char 数组的结尾。这就是为什么我会将数组大小作为参数传递
        • 这是我最喜欢的解决方案,但 C 风格的转换并不好。我现在正试图找出一种以某种方式使用static_cast 的方法。
        猜你喜欢
        • 2019-08-10
        • 1970-01-01
        • 1970-01-01
        • 2017-03-24
        • 2013-07-20
        • 1970-01-01
        • 2015-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多