Is there a shorter way to initialize a QByteArray?

In my program I work a lot with serial communication so QByteArray is used very often.

I was wondering if there was a shorter way to initialize a QByteArray with specific bytes than:

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));

The static_cast<char> is necessary because otherwise C++11 gives an error about narrowing, because the range 0x7F to 0xFF is bigger than a char could fit--but a char is what the QByteArray constructor asks for.

This is the QByteArray constructor being used:

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

Answers


Simple and effective:

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

As an alternative to QByteArrayLiteral, you can roll your own, if you wish:

#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);
}

like this:

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

now QByteArray constructor looks weird, but byte sequences are clear. You can also add terminating 0-byte to array instead of using std::extent, but in general you can have zero-bytes in the middle of sequence.


Being inspired by the answers above this is what I finally came up with:

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

I much prefer to have the bytes as byte numbers rather than literal characters when working with serial communication.

After having a discussion on ##c++ I was advised that reinterpret_cast is appropriately used in this situation.


May be works slowly:

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

Have you tried the following:

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));

You are using the constructor: QByteArray::QByteArray(const char *data, int size = -1).

If size is negative, data is assumed to point to a nul-terminated string and its length is determined dynamically. The terminating nul-character is not considered part of the byte array.


Need Your Help

How does the command prompt know when to wait for exit?

c# windows command-prompt

I was attempting to do a Windows command prompt re-code in C#. I was wondering how the command prompt knows when to wait for the process started to exit, and when not to wait for the called process...

Show twitter bootstrap modal dialog automatically with knockout

twitter-bootstrap knockout.js

I need to show modal dialog for editing item in single page app when I select an item from list.