将 unsigned char 转换为 signed char 以获得红黑树
Posted
技术标签:
【中文标题】将 unsigned char 转换为 signed char 以获得红黑树【英文标题】:Casting unsigned char to signed char for a red-black tree 【发布时间】:2018-06-06 08:20:56 【问题描述】:概述
我正在使用 Qt 封装 Windows Shell 功能。我遇到的问题与ABSOLUTE_IDLIST
s 和存储数据有关。作为参考,一个
Windows id 列表在内存中是这样的:
//Note that there may be an arbitrary number of cb/abId pairs.
=================================================================
= = (cb bytes) = = (cb bytes) = =
= USHORT cb = UCHAR []abID = USHORT cb = UCHAR []abId = '\0' =
=================================================================
我使用绝对 ID 作为每个节点的唯一标识符以便快速
恢复。值类型为ShellNodePointer
,一个指向ShellNode
的共享指针,用于缓存数据。我最初使用
QHash
(基本上是 std::unordored_map
),但这需要对每次检索的位进行哈希处理(尽管我将哈希键存储在 ShellNode 中)。
//unsigned int is the hash result, ShellNodePointer is a QSharedPointer to a ShellNode
QHash<unsigned int, ShellNodePointer>
相反,我正在考虑使用QMap
的红黑树方法。我的问题是
this:比较两个键的最快方法是将它们存储为QByteArray
s,这将允许快速小于比较并将id列表作为原始数据简单地传递给QByteArray
构造函数。
ITEMIDLIST_ABSOLUTE *someIdListPointer = ...;
QByteArray ba(someIdListPointer);
问题
不幸的是,QByteArray 采用以空结尾的const char *
,没有
指定签名或未签名。由于我在 Windows 上,因此默认为已签名
字符。
问题
我可以转换为[signed] char *
并忽略溢出问题,因为每个负值键都会以同样的方式溢出吗?具体来说,红黑树是否仍能正常工作,因为在使用相同键的两个单独调用中保证生成的数据是一致的?
注意:我知道USHORT cb
将包含在密钥中。这是可以接受的,因为它只是将与两个相同的键匹配的额外数据。
编辑:澄清abId
实际上是一个没有空终止符的数组。
【问题讨论】:
哪些溢出问题?将指针转换为不同的类型意味着您以不同的方式解释字节(就像其他有符号/无符号转换一样)并且不可能溢出。此外,虽然标准不保证有符号整数类型的二进制补码表示,但这是一个非常安全的假设。 我是这么想的,但我想确保在比较密钥时不会遇到问题。 假设您不关心 RB 树中的实际顺序,您可以以任何您想要的方式处理/查看数据字节以进行比较,甚至像int32_t
s (假设列表正确对齐)。那么两者的补码也无关紧要。当只有整个列表以空字符结尾而不是单个键时,QByteArray
采用以空字符结尾的字符序列之间的差异让我更加困惑。但也许这是我的一个误解。
关于空终止:cbID
不是空终止,只有整个结构。
什么是cbID
?
【参考方案1】:
我可以转换为 [signed] char * 并忽略溢出问题,因为每个负值键都会以相同的方式溢出吗?具体来说,红黑树是否仍能正常工作,因为在使用相同键的两个单独调用中保证生成的数据是一致的?
是的,像这样的转换只是以不同的方式解释内存中的字节,并且对于相同的机器 + 可执行文件/编译器是一致的。标准没有强制要求有符号整数的字节表示,因此“含义”(即表示的数字)可能不是您所期望的,但这对于只需要总排序的 RB 树来说并不重要。
【讨论】:
感谢您的帮助和耐心,Max。以上是关于将 unsigned char 转换为 signed char 以获得红黑树的主要内容,如果未能解决你的问题,请参考以下文章
C语言 请问signed char,unsigned char,short,unsigned sh
为什么C或C ++标准没有明确地将char定义为signed或unsigned?
将 bigint unsigned 列转换为 bigint signed 失败