有没有一种更短的方法来初始化 QByteArray?

14

我的程序经常涉及串行通信,因此经常使用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));

由于范围0x7F到0xFF比char所能容纳的范围更大,因此C++11会出现缩小错误,因此需要使用static_cast<char>,但是QByteArray构造函数要求传入char

这是被使用的QByteArray构造函数:

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


@OnurA 你确定需要使用星号吗?初始化test_data的那一行会抛出“从'int'到'const unsigned char*'的无效转换”错误。 - DBedrenko
你可以轻松地创建一个函数,该函数以你想要的参数创建一个 QByteArray - Garf365
你的任何一个字节值可以是 0x00 吗?如果不行,你可以使用带有字符串字面量的 const char* 构造函数。 - Jimmy
抱歉造成困惑,数组实际上是一个指针,这就是我所说的。在你的情况下,应该是: const unsigned char test_data[] = {...} 然后你可能需要使用:QByteArray((char*)test_data) - OnurA
1
@Jimmy 你说得对,可以将"\x01\xB2\xB4"传递给构造函数,但最好使用整数(可以使用常量名称等)。不过我应该能够有一个“0”字节... - DBedrenko
显示剩余4条评论
6个回答

36

简单而有效:

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

我没有在任何地方看到QByteArrayLiteral的文档,但是它比传递给QByteArray的完全相同的参数更有效,因为"\x00"不被视为字符串终止符。使用QByteArray也可以实现相同的效果,但必须传递正确的size参数。这不是一个坏的解决方案,谢谢 :) - DBedrenko
1
{btsdaf} - rbaleksandar
2
我想知道是谁记录了那个... - peppe
仅从Qt5开始呈现 - garlix
2
任何其他主要版本的Qt都已经到达了生命周期结束(EOL)。 - peppe
不错!值得一提的是,QByteArrayLiteral将允许写入x00字节,而不是表示“结束”。 - Francisco D. Hurtado

5
作为的替代方案,如果您愿意,您可以自己编写:
#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);
}

5

可能会运行缓慢:

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


3

就像这样:

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是必要的吗? - OnurA
3
我喜欢 reinterpret_cast(C++ 风格,而不是 C)。不要使用 extent,只需使用 sizeof(str)。 - Aconcagua
1
你不能只是将 str 强制转换而不是 &str[0](对我来说看起来很丑)吗?至少 GCC 可以接受... - Aconcagua

0
你尝试过以下内容吗:
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指向以空字符结尾的字符串,并动态确定其长度。终止的空字符不被视为字节数组的一部分。


1
我刚试了一下,它成功编译了。它可以在没有所有的 static_cast 的情况下工作(你的解决方案的整个好处就是不需要这些转换)。我不确定在处理 0 字节时应该注意什么:我需要能够使用 0 字节。 - DBedrenko
1
你绝对需要调用 QByteArray((char*) test_data, sizeof(test_data));!单参数构造函数(或大小为-1的构造函数)将尝试像普通C字符串一样复制数据,这需要以空字符结尾! - Aconcagua
1
如果你的字符数组中间有一个0x00,它会将其检测为字符数组的结尾。这就是为什么我会将数组大小作为参数传递的原因。 - OnurA
这是我最喜欢的解决方案,但 C 风格的转换不好。我现在正在尝试找出一种使用 static_cast 的方法。 - DBedrenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接