c++ - Qt:QML Int溢出

标签 c++ qt qml qt5 integer-overflow

在我的Qt应用程序中,我试图将较大的整数值从C++代码传递给QML。
在我的C++中,我有一个Q_PROPERTY(int ...),但显然int有时不足以满足我的应用程序的需要,并且溢出。
我可以在QML中使用长类型或无符号类型吗?动态大小的int类型如何?
从QML文档中,我所能找到的都是int,范围为“-2000000000到2000000000左右”。
任何帮助表示赞赏! =)

最佳答案

我觉得您的问题很有趣,因为它一开始看起来很琐碎,尽管在获取答案的方式上却提出了很多观点。

我假设您想将64位整数从C++传递给QML。我稍后解释。

用于64位整数的QML基本类型

没有64位整数QML basic type,因此您不能期望将C++值转换并存储在这样的不存在的QML类型属性中。如文档中所述,Qt模块可以扩展可用类型的列表。我们甚至可以想到一个将来可以添加自己的类型的 future ,但如今不行:

Currently only QML modules which are provided by Qt may provide their own basic types, however this may change in future releases of Qt QML.



有人可能会认为,在64位平台上编译其应用程序应该可以完成这项工作,但不会改变任何事情。关于这个问题有a lot of answers。为了清楚起见,这是在同一台计算机上使用32位和64位编译器对结果进行的比较:

在具有32位编译器(mingw53)的64位系统(Windows 7 64位)的计算机(64位处理器:Core i7)上,我已经
 4 = sizeof(int) = sizeof(long) = sizeof(int*) = sizeof(size_t)

我把size_t弄清楚了,它不能用于表示文件大小,不是its purpose

在同一系统上使用64位编译器(msvc2017,x64):
 4 = sizeof(int) = sizeof(long)
 8 = sizeof(int*) = sizeof(size_t)

使用64位编译器不会更改sizeof(int),因此认为intint*的大小相同显然是错误的。

在您的情况下,您似乎要存储文件大小,而32位不足以表示文件大小。因此,如果我们不能依靠int来执行此操作,则应使用哪种类型?

文件大小类型大小

现在,我认为64位整数应该足够了,并且是存储文件大小的正确方法。但这是真的吗?根据cplusplus.com,此类型为std::streampos。如果您在cppreference.com上查找详细信息,则会发现std::streamposstd::fpos的特化,并描述了其典型实现:

Specializations of the class template std::fpos identify absolute positions in a stream or in a file. Each object of type fpos holds the byte position in the stream (typically as a private member of type std::streamoff) and the current shift state, a value of type State (typically std::mbstate_t).



std::streamoff的实际类型可能是64位有符号整数:

The type std::streamoff is a signed integral type of sufficient size to represent the maximum possible file size supported by the operating system. Typically, this is a typedef to long long.



另外,在同一页面上,您可以阅读:

a value of type std::fpos is implicitly convertible to std::streamoff (the conversion result is the offset from the beginning of the file).

a value of type std::fpos is constructible from a value of type std::streamoff



让我们再看看32位或64位目标平台所具有的功能。

使用32位编译器
  8 = sizeof(long long) = sizeof(std::streamoff)
 16 = sizeof(std::streampos)

它表明,显然,比现在知道文件大小所需的信息更多的信息存储在std::streampos中。

在同一系统上使用64位编译器:
  8 = sizeof(long long) = sizeof(std::streamoff)
 24 = sizeof(std::streampos)
sizeof(std::streamoff)的值未更改。可能有。在两种情况下,它都必须足够大才能存储文件大小。您可能需要使用std::streamoff在C++端存储文件大小。您不能依靠它是64位。
让我们假设有人想冒一个风险,即假设它是64位,如这些示例所示:仍然存在将其作为基本类型传递给QML以及可能传递给Javascript引擎的问题。

尽管如此,在QML中使用了接近64位

如果只需要将大小显示为以字节为单位的数字,则UI中将需要文本表示。您可以坚持这个想法,使用字符串,而不必传递整数值。
如果您需要使用Javascript在QML方面进行算术运算,除非您不使用核心语言进行算术运算,否则您可能会碰到Javascript Number53 bit barrier

在这里,如果您假设文件大小不能大于2 ^ 53,则可以使用double。您必须知道this answer中所述如何在目标平台上处理double类型,如果足够幸运的话,它将具有不损失53位整数值的存储能力。之后,您可以直接在Javascript中对其进行操作,并且保证可以正常运行,至少在ECMA 262版本8中如此。

现在可以了吗?我们可以对小于2 ^ 53的任何文件使用 double 吗?

好吧……Qt不一定实现ECMAScript的最新规范,而是使用several implementations
在Webviews中,它确实使用了rather common implementation
在QML中,它使用基于ECMA 262版本5的自己的,未记录的内置Javascript引擎。此版本的ECMA没有明确提及一个值,所有较小的整数值都必须保证存储在Number中。这并不意味着它将无法正常工作。即使已提及,该实现也仅基于规范,并不要求合规。您可能会发现自己很不幸地需要长时间工作,然后在更新的Qt版本中发现它不再起作用。

看来必须做出许多假设。在基于它的软件的整个生命周期中,所有这些可能都是并且可能会保持正确。因此,这是应对风险的问题。

有没有办法降低想要降低的风险?

不冒一点点正确性的风险

我看到两条主要路径:
  • 根本不用理会所有这些东西。例如,使用double,并在看起来可行的范围内做任何您想做的事情。如果对于没有发生的情况不起作用,为什么要尝试处理它们?当它不起作用时,您将处理它。
  • 试图变得更加严格,并以更健壮的方式做到这一点。据我了解,这种解决方案可能是将所有文件大小算法保留在C++端,并且仅将安全值传递到QML端。例如,用于测试的 bool(boolean) 值和用于显示大小值(总大小,剩余大小等)的字符串。您无需担心任何内容中有多少位。

  • 提示:bittorent protocol使用字符串来编码大小。

    问题不仅限于QML属性

    如果您使用Javascript对Number实例操作整数值,并将其用作QML信号的int参数的参数,则可能会出现相同的问题。例如,声明这样的信号:
      signal sizeChanged(var newSize) // Number class (maybe 53 bit) integral value possible
    

    可能处理以下情况肯定无法解决的情况:
      signal sizeChanged(int newSize) // 32 bit int limitation
    

    失败的一个例子是传递(new Date()).getTime()
    这是相同的限制,不限于与QML进行C++属性交互。

    关于c++ - Qt:QML Int溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25709429/

    相关文章:

    c++ - 如何检查VS C++标准版本

    c++ - 存储一位小数

    c++ - Mongodb : error while loading shared libraries: libboost_thread. so.1.54.0: > 无法打开共享对象文件:没有这样的文件或目录

    c++ - 使用 softmax 进行 Action 选择?

    c++ - 使用 CMake、Clang 和 Ninja 在 Windows 上构建 c++ 项目

    qt - 为什么我的线宽在具有相同 QPen 宽度的 QGraphicsScene 中看起来不同?

    qt - Qt应用程序的多平台崩溃报告系统

    c++ - Qt5-QML : How to modify bindings to change Text after ProgressBar finishes loop

    qt - 使用 CMake 构建 Qt Qml 插件

    从 qrc 导入 qml 时 QtCreator 语法突出显示