Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将QByteArray强制转换为“long”会为相同的输入输出不同的结果_C++_Qt_Casting_Qt5.6 - Fatal编程技术网

C++ 将QByteArray强制转换为“long”会为相同的输入输出不同的结果

C++ 将QByteArray强制转换为“long”会为相同的输入输出不同的结果,c++,qt,casting,qt5.6,C++,Qt,Casting,Qt5.6,编辑:添加完整的MCV示例项目。 我有一个奇怪的问题,相同的代码和相同的输入产生不同的输出值 代码的目的是测试一个函数,该函数将一个值压缩为4个字节,然后将其解压为单个32位值。test_unpack()中的value1、value2和value3的预期值为2018915346(即0x78563412,因为小端数解包)。我从你那里得到了这种解包的方法。下面是一个MCV示例,您可以轻松构建并亲自查看问题。请注意,如果注释掉test1()test\u unpack()的主体,则会神奇地传递正确的值

编辑:添加完整的MCV示例项目。

我有一个奇怪的问题,相同的代码和相同的输入产生不同的输出值

代码的目的是测试一个函数,该函数将一个值压缩为4个字节,然后将其解压为单个32位值。
test_unpack()
中的
value1
value2
value3
的预期值为2018915346(即0x78563412,因为小端数解包)。我从你那里得到了这种解包的方法。下面是一个MCV示例,您可以轻松构建并亲自查看问题。请注意,如果注释掉
test1()
test\u unpack()
的主体,则会神奇地传递正确的值

测试\u canserialcomm.cpp

#include "test_canserialcomm.h"

#include <QtTest/QtTest>
#include <QByteArray>

long unpack() noexcept
{
    quint8 a_bytes[] = {0x12, 0x34, 0x56, 0x78};
    QByteArray a = QByteArray(reinterpret_cast<char*>(a_bytes), 4);
    long value1 = *((long*)a.data());
    qDebug() <<  value1; // outputs "32651099317351442" (incorrect value)

    quint8 b_bytes[] = {0x12, 0x34, 0x56, 0x78};
    QByteArray b = QByteArray(reinterpret_cast<char*>(b_bytes), 4);
    long value2 = *((long*)b.data());
    qDebug() << value2; // outputs "2018915346" (correct value)

    quint8 c_bytes[] = {0x12, 0x34, 0x56, 0x78};
    QByteArray c = QByteArray(reinterpret_cast<char*>(c_bytes), 4);
    long value3 = *((long*)c.data());
    qDebug() << value3; // outputs "2018915346" (correct value)

    return value1;
}

void TestCanSerialComm::test1()
{
    QCOMPARE("aoeu", "aoeu"); // If you comment this line, the next test will pass, as expected.
}

void TestCanSerialComm::test_unpack()
{
    long expected {0x78563412};
    QCOMPARE(unpack(), expected);
}
#include <QtTest>
#include "test_canserialcomm.h"
#include <QCoreApplication>

int main(int argc, char** argv) {
    QCoreApplication app(argc, argv);
    TestCanSerialComm testCanSerialComm;
    // Execute test-runner.
    return QTest::qExec(&testCanSerialComm, argc, argv); }
尽管代码和输入相同,但
test_unpack()
中的
value1
输出错误。奇怪的是,如果我删除
qDebug()
调用并设置断点,调试器表达式计算器现在会显示
value2
的值是错误的

知道为什么会这样吗?甚至如何进一步排除故障


附加说明:如果我添加一行
qDebug()您在系统上编译和运行此程序,其中
long
为8字节,但您的
QByteArray
只有4字节。这意味着,当您将数组别名为
long
(使用
*((long*)a.data())
)时,您正在将数组末尾的4个字节读入未初始化的堆存储中

修复方法是使用保证为4字节大小的类型,例如
std::int32\t

另一方面,使用
*((long*)[…])
来别名内存不能保证工作,主要是因为对齐问题,而且(在一般情况下)因为别名仅支持与
char
有符号
无符号
变体等效的类型。更安全的方法是使用
memcpy

std::uint32_t value1;
assert(a.size() == sizeof(value1));
memcpy(&value1, a.data(), a.size());

您正在编译和运行此程序的系统中,
long
是8个字节,但您的
QByteArray
只有4个字节。这意味着,当您将数组别名为
long
(使用
*((long*)a.data())
)时,您正在将数组末尾的4个字节读入未初始化的堆存储中

修复方法是使用保证为4字节大小的类型,例如
std::int32\t

另一方面,使用
*((long*)[…])
来别名内存不能保证工作,主要是因为对齐问题,而且(在一般情况下)因为别名仅支持与
char
有符号
无符号
变体等效的类型。更安全的方法是使用
memcpy

std::uint32_t value1;
assert(a.size() == sizeof(value1));
memcpy(&value1, a.data(), a.size());

看看这些值在内存中的表示形式,可能会给出一个线索(我没有qt)-另一个想法:为什么不使用一个简单的联合来实现这一点?@slashmais感谢您的提示。“内存表示法”是指设置断点时在调试器中看到的变量值吗?这些值与
qDebug()
输出相同。我不确定在这种情况下如何使用并集。我运行了你的代码,对所有三个值都得到了相同的结果。在你的系统上,
long
的大小是多少?所谓内存中,我指的是你查看包含值/变量的内存地址-可能有助于你发现ecatmur建议的内容。请查看这些值的内存表示形式,可能会给你一个线索(我没有qt)-另一个想法:为什么不使用一个简单的联合来完成这个任务?@slashmais谢谢你的提示。“内存表示法”是指设置断点时在调试器中看到的变量值吗?这些值与
qDebug()
输出相同。在这种情况下,我不确定如何使用union。我运行了您的代码,对所有三个值都得到了相同的结果。您的系统上的
long
大小是多少?所谓内存中,我的意思是您查看包含值/变量的内存地址-可能有助于您发现ecatmur建议的内容。
std::uint32_t value1;
assert(a.size() == sizeof(value1));
memcpy(&value1, a.data(), a.size());