[英]Match implementation specific C++ char to uint32_t cast in Python
请考虑以下C ++程序:
#include <cstdint>
#include <iostream>
int main() {
std::string s = "αa";
std::cout << std::hex << uint32_t(s[0]) << std::endl;
std::cout << std::hex << uint32_t(s[1]) << std::endl;
std::cout << std::hex << uint32_t(s[2]) << std::endl;
}
哪个打印
ffffffce
ffffffb1
61
如何在Python中复制转换行为? IE浏览器。 如何获取包含3个数字的uint32_t类型的numpy数组? 1
例如
import numpy as np
s = "αa"
s = s.encode('utf-8')
for c in bytearray(s):
h = print(hex(np.uint32(c)))
将导致
0xce
0xb1
0x61
这还不够。 我也研究了ctypes模块提供的功能,但找不到可行的解决方案。
动机:我想应用一个Fowler-Noll-Vo哈希函数 ,该函数依赖于按位运算,并与通过将std::string
的元素转换为uint32_t
操作的现有C ++实现相匹配。
1虽然C ++版本的输出取决于体系结构/编译器,但我正在寻找一种实现方案,该实现方案与该问题中描述的行为匹配,或者与使用python解释器的编译器相同的编译器进行编译时,C ++程序的行为匹配继续。
根据Python文档。 :
字节数组类型是一个可变的整数序列,范围为0 <= x <256。
恕我直言,因此C ++中的转换应将字符处理为unsigned char
。 这可以通过“两步”强制转换来实现:
#include <cstdint>
#include <iostream>
typedef unsigned char uchar;
int main() {
std::string s = "αa";
std::cout << std::hex << uint32_t((uchar)s[0]) << std::endl;
std::cout << std::hex << uint32_t((uchar)s[1]) << std::endl;
std::cout << std::hex << uint32_t((uchar)s[2]) << std::endl;
}
输出:
ce
b1
61
笔记:
我认为初始化std::string s = "αa";
有点关键。 因此,这取决于源代码编码。 (我在Windows上。许多Windows应用程序通常都使用Windows-1252编码会破坏该程序, 因为字符串仅包含两个元素 。我只是意识到Window-1252甚至不编码α
但是并没有使它变得更好。)
强制将字符设置为unsigned char
,应使应用程序独立于C ++编译器的特定char
类型的签名。
这里的问题是,您的C ++实现(标准所做的很多事情,不幸的是允许但没有强制执行 )将char
作为有符号类型,而Python正确地将bytearray
元素视为非负值。
IMO的正确解决方案将如@Scheff在他的答案中所示-修复C ++程序,该程序依赖于实现定义的行为,该行为会产生有争议的输出。 OTOH,如果您不得不匹配无法更改的现有C ++程序,则可以轻松地在Python中重现此行为。
在您的C ++程序中,当超出127的字节值(因此为负)转换为uint32_t
,它将被包裹在ffffffxx
左右,因此所有ffffffxx
值都将被包装。
为了在Python中获得相同的结果,您可以先手动将其转换为int8
(即C ++实现中的char
):
import numpy as np
s = "αa"
s = s.encode('utf-8')
for c in bytearray(s):
h = print(hex(np.uint32(np.int8(c))))
输出:
0xffffffce
0xffffffb1
0x61
第一个字符为0xffffffce
的事实取决于实现,并且有效的C ++实现也可能返回0xce
因为差异取决于默认的char
类型是带符号的还是无符号的(某些编译器提供了命令行开关来更改行为,因此不是甚至仅依赖于平台,但依赖于编译选项)。
也就是说,您可以通过简单地扩展第8位或在转换之前将其转换为相应的带符号的值,将转换为uint32的无符号字符固定为与带符号的字符转换相同的结果。例如
print(hex(np.uint32(c if c < 128 else c-256)))
获取uint32的numpy数组的一种方法是首先将其传递给int8数组:
>>> s = 'αa'
>>> a = np.array(list(s.encode('utf8')),dtype=np.int8)
>>> b = np.array(a,dtype=np.uint32)
>>> b
array([4294967246, 4294967217, 97], dtype=uint32)
>>> for c in b: print(hex(c))
...
0xffffffce
0xffffffb1
0x61
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.