Appending a std::uint16_t literal constant to a QByteArray
-
I am trying to append the two bytes of a
std::uint16_t
literal constant to aQByteArray
as follows:const std::uint16_t FOO = 0x8901; QByteArray ba; ba.append(FOO);
The 0x89 byte should come first, the 0x01 byte second.
Unerstandably, because
QByteArray::append
expects a char, this does not work. I get the following warning:warning C4305: 'argument': truncation from 'const uint16_t' to 'char' warning C4309: 'argument': truncation of constant value
What would be the most elegant way to accomplish this? I was thinking of using one of the other overloads of
QByteArray::append
, but currently don't see how. -
I am trying to append the two bytes of a
std::uint16_t
literal constant to aQByteArray
as follows:const std::uint16_t FOO = 0x8901; QByteArray ba; ba.append(FOO);
The 0x89 byte should come first, the 0x01 byte second.
Unerstandably, because
QByteArray::append
expects a char, this does not work. I get the following warning:warning C4305: 'argument': truncation from 'const uint16_t' to 'char' warning C4309: 'argument': truncation of constant value
What would be the most elegant way to accomplish this? I was thinking of using one of the other overloads of
QByteArray::append
, but currently don't see how.@Bart_Vandewoestyne
Same as before ;)QByteArray ba; ba.append("\x89\x01");
-
I am trying to append the two bytes of a
std::uint16_t
literal constant to aQByteArray
as follows:const std::uint16_t FOO = 0x8901; QByteArray ba; ba.append(FOO);
The 0x89 byte should come first, the 0x01 byte second.
Unerstandably, because
QByteArray::append
expects a char, this does not work. I get the following warning:warning C4305: 'argument': truncation from 'const uint16_t' to 'char' warning C4309: 'argument': truncation of constant value
What would be the most elegant way to accomplish this? I was thinking of using one of the other overloads of
QByteArray::append
, but currently don't see how.@Bart_Vandewoestyne said in Appending a std::uint16_t literal constant to a QByteArray:
The 0x89 byte should come first, the 0x01 byte second
That implies big-endian.
const std::uint16_t FOO = 0x8901; QByteArray ba; QDataStream baStream(&ba,QIODevice::Append); // baStream.setByteOrder(QDataStream::BigEndian); <- already the default baStream << quint16(FOO);
-
@Bart_Vandewoestyne
Same as before ;)QByteArray ba; ba.append("\x89\x01");
@kshegunov said in Appending a std::uint16_t literal constant to a QByteArray:
QByteArray ba; ba.append("\x89\x01");
Yes, I know that works, but I want to avoid magic constants in my code. I really would like to use the constant variable name... and the constant is defined as
const std::uint16_t FOO = 0x8901;
-
@kshegunov said in Appending a std::uint16_t literal constant to a QByteArray:
QByteArray ba; ba.append("\x89\x01");
Yes, I know that works, but I want to avoid magic constants in my code. I really would like to use the constant variable name... and the constant is defined as
const std::uint16_t FOO = 0x8901;
@Bart_Vandewoestyne said in Appending a std::uint16_t literal constant to a QByteArray:
and the constant is defined as
You can't define it in a different manner? E.g.:
static const char foo[2] = { '\x89', '\x01' };
If not, then @VRonin's suggestion is probably wisest.
-
Just for completeness (not necessarily recommending this) it is possible to use
FOO
as thestd::uint16_t
is already is, and without needing to use aQDataStream
object, like:const std::uint16_t FOO = 0x8901; QByteArray ba; const auto localEndian = qFromBigEndian(FOO); ba.append(reinterpret_cast<const char *>(&localEndian), sizeof(FOO));
Again, not saying its the best approach, but it might optimal (both memory and speed) for some scenarios? :)
I know the
reinterpret_cast
can look a bit concerning, but it is perfectly valid here. However, IMO, you'd still need a some strong requirement (such as important performance optimisation) to justify this slightly less readable solution.Just some food for thought...
Cheers.
-
@kshegunov said in Appending a std::uint16_t literal constant to a QByteArray:
QByteArray ba; ba.append("\x89\x01");
Yes, I know that works, but I want to avoid magic constants in my code. I really would like to use the constant variable name... and the constant is defined as
const std::uint16_t FOO = 0x8901;
@Bart_Vandewoestyne
to play devils advocate,
theres alwaysQByteArray::number
const std::uint16_t FOO = 0x8901; QByteArray ba; ba.append(QByteArray::number(FOO));
Never mind, just tested it does not work as I would have expected it! -
const std::uint16_t FOO = 0x8901; QByteArray ba; ba.append(char(FOO & 0xFF)); // 0x01 ba.append(char(FOO >> 8)); // 0x89 // or ba.append(static_cast<char*>(static_cast<void*>(&FOO)), sizeof(FOO));
Hi @fryn3,
while your first part looks good as universal solution, the second part
ba.append(static_cast<char*>(static_cast<void*>(&FOO)), sizeof(FOO));
will only work as demanded on big endian systems, which are the minority nowadays.
Regards
-
Hi @fryn3,
while your first part looks good as universal solution, the second part
ba.append(static_cast<char*>(static_cast<void*>(&FOO)), sizeof(FOO));
will only work as demanded on big endian systems, which are the minority nowadays.
Regards
@aha_1980 it's work.
#include <iostream> using namespace std; int main() { uint16_t t = 0x8901; cout << hex << int(t & 0xFF) << " " << int(t >> 8) << endl; cout << hex << int(*(uint8_t*)&t) << " " << int(*(((uint8_t*)&t) + 1)); return 0; } // output: 1 89 1 89
-
I have read the demand again, and it's like this:
The 0x89 byte should come first, the 0x01 byte second.
So the only portable way to do is your proposal, slightly adopted by me:
const std::uint16_t FOO = 0x8901; QByteArray ba; ba.append(char(FOO >> 8)); // 0x89 ba.append(char(FOO & 0xFF)); // 0x01
Static casting the 16-Bit word is not endian-awere, the same applies for this one:
cout << hex << int((uint8_t)&t) << " " << int((((uint8_t)&t) + 1));
which is by the way, wrong as 0x01 comes first here.
And if you try this on a big endian machine, it will give other results.
Regards