将QString转换为uintptr_t,Qt / C ++

时间:2017-04-19 12:24:41

标签: c++ qt types casting

当我将模拟的状态存储在json文件中时,我想使用对象的地址作为唯一标识符。因此,我将指向我的对象的指针转换为uintptr_t

Cat myCatptr = new Cat;
uintptr_t address= (uintptr_t)myCatptr;

现在我将address转换为QString:

QString str = QString::number(address); 

然后我可以轻松地将QString添加到QJsonObject。但是如何从QString转换回uintptr_t?

在我的机器上,我知道sizeof(unsigned long long)sizeof(uintptr_t )都是8字节。因此我可以使用

address= (uintptr_t)str.toULongLong();

这是否始终正确,独立于平台?这需要这样做 适用于所有平台的sizeof(uintptr_t) <= sizeof(unsigned long long)

如上所述heresizeof(unsigned long long) is always >= 8byte

再次总结:

  1. 我的Ansatz,将其转换为unsigned long long然后再转换为uintptr_t始终有效吗?

  2. 如果没有,您是否知道可以在任何平台上运行的替代方案?

3 个答案:

答案 0 :(得分:1)

标准是否有保障?没有。想象一个qulonglong为64位的平台是完全可行的,但uintptr_t是一种神奇的256位扩展类型。

另一方面,a)目前不存在这样的平台; b)即使qulonglong是64位,Qt也可能在该平台上将unsigned long long定义为256位; c)您没有太多选择:给定QString,您可以轻松将其转换为qulonglong的最长整数。

100%便携式解决方案是使用scanfSCNxPTR(这是将文本转换为uintptr_t的格式。

    const auto text = str.toStdString();            // Convert to std::string
    sscanf( text.c_str(), "%" SCNxPTR, &address );  // Convert to uintptr_t
    // additional error handling required.

扫描文件的一般文件here。一般形式是:

sscanf( pointer_to_const_char_array, format, &value1, &value2, ... );

uintptr_tSCNxPTR的文档是here(我实际上是通过this answer找到的。SCNxPTR是一个#define宏,它扩展为string literal,它是提供给sscanf(以及scanf系列中的其他人)以十六进制解码uintptr_t的正确格式。

答案 1 :(得分:0)

它应该可以正常工作,无论您使用哪个当代平台,都有足够的空间来容纳指针。实际上,你可能会有点过分,你可以直接指向qulonglong并返回。我已经在x86和arm,32位和64位版本上对此进行了测试。

您还可以将指针放在特定平台上的任何大小,并将其移动到字节数组中,然后使用base64编码从该数据创建一个字符串,并在转换回时执行相反的操作。无论该平台上的指针大小如何,都应该备份这个。

还有另一种更好的方法。您可以实现QHash<int, Cat *>注册表,而不是直接使用指针,为每个cat分配一个唯一的整数id,并将其与内存中的地址相关联。这具有跨应用程序运行持久化的优点,因此即使每次在加载时重新创建应用程序数据时其地址都发生更改,您也可以始终寻址该特定对象。既然你提到&#34;存储状态&#34;我假设您希望以跨应用程序运行的方式存储它。您将无法保证,并且在下次应用程序运行时将对象分配到同一地址几乎是不可能的,因此任何保存的指针值都将无用。因此,可选的解决方案是将实际指针与将持久存在的整数id相关联,查找也可能比将字符串来回转换为整数更快。

答案 2 :(得分:0)

我也认为我找到了解决方案。如果你发现任何错误,也许你可以对它发表评论。

我的解决方案使用QVariant。我注册了数据类型uintptr_t,以便QVariant知道它:

在Qt核心中定义的

Q_DECLARE_METATYPE(uintptr_t);

则...

Strand * myCatptr = strand;
uintptr_t address= (uintptr_t)myCatptr;
QString str = QString::number(address);

//string can be passed to QJsonObject
//...
//string gets loaded from QJasonObject again to a later point.

//Variant can be converted to uintptr_t, because I registered it
QVariant var = QVariant::fromValue(str);
address = var.value<uintptr_t>();

通过QVariant将QString转换为uintptr_t。