如何在不泄露uint64_t信息的情况下将uint8_t[8]转换为C++?
我尝试了以下几点:
uint64_t number = 23425432542254234532;
uint8_t result[8];
for(int i = 0; i < 8; i++) {
std::memcpy(result[i], number, 1);
}发布于 2016-02-02 12:08:05
例如,如果我正确理解,您可以这样做:
uint64_t number = 23425432542254234532;
uint8_t *p = (uint8_t *)&number;
//if you need a copy
uint8_t result[8];
for(int i = 0; i < 8; i++) {
result[i] = p[i];
}发布于 2016-02-02 12:24:07
你快到了。首先,文字23425432542254234532太大,不适合于uint64_t。
其次,从文档中可以看到,std::memcpy有以下声明:
void * memcpy ( void * destination, const void * source, size_t num );如您所见,它以指针(地址)作为参数。不是uint64_t,也不是uint8_t。您可以使用address-of运算符轻松地获得整数的地址。
其次,您只是将整数的第一个字节复制到每个数组元素中。您需要在每次迭代中增加输入指针。但是循环是不必要的。您可以一次复制所有字节,如下所示:
std::memcpy(result, &number, sizeof number);请注意,字节的顺序取决于cpu的痴呆症。
发布于 2018-12-16 22:45:00
首先,您希望转换为大端还是小端?前面的大多数答案将开始以相反的顺序给出字节,并在切换架构后立即中断您的程序。
如果需要获得一致的结果,则需要将64位输入转换为大端(网络)字节顺序,或者可能转换为小端字节。例如,在glib上,函数是GUINT64_TO_BE(),但是对于大多数编译器来说,有一个等效的内置函数。
在这样做之后,有几种选择:
用memcpy()或memmove()复制
这是语言标准所保证的方法,尽管这里我使用了第三方库中的一个函数(在所有平台上将参数转换为大端字节顺序)。例如:
#include <stdint.h>
#include <stdlib.h>
#include <glib.h>
union eight_bytes {
uint64_t u64;
uint8_t b8[sizeof(uint64_t)];
};
eight_bytes u64_to_eight_bytes( const uint64_t input )
{
eight_bytes result;
const uint64_t big_endian = (uint64_t)GUINT64_TO_BE((guint64)input);
memcpy( &result.b8, &big_endian, sizeof(big_endian) );
return result;
}在具有x86_64的Linux clang++ -std=c++17 -O上,这从本质上编译为以下说明:
bswapq %rdi
movq %rdi, %rax
retq如果您希望在所有平台上以小端点顺序执行结果,可以用GUINT64_TO_BE()替换GUINT64_TO_LE()并删除第一条指令,然后声明函数inline以删除第三条指令。(或者,如果您是,即跨平台兼容性并不重要,那么您可能只需冒忽略规范化的风险。)
因此,在现代的64位编译器上,这段代码与其他任何代码一样高效。在另一个目标上,可能不是。
双关式
用C编写它的常见方法是像以前一样声明union,设置它的uint64_t成员,然后读取它的uint8_t[8]成员。这在C.
我个人喜欢它,因为它允许我将整个操作表示为静态的单个任务。
然而,在C++中,它是形式上未定义的行为。在实践中,我所知道的所有C++编译器都支持相同大小的朴素旧数据(语言标准中的正式术语),没有填充位,但不支持具有虚拟函数表等更复杂的类。在我看来,标准的未来版本更有可能正式支持对POD的类型双关,而不是任何重要的编译器都会悄无声息地破坏它。
C++指导方法
Bjarne建议,如果要键入双关语而不是复制,则使用reinterpret_cast,如
uint8_t (&array_of_bytes)[sizeof(uint64_t)] =
*reinterpret_cast<uint8_t(*)[sizeof(uint64_t)]>(
&proper_endian_uint64);他的推理是,在union中显式的强制转换和类型双关都是未定义的行为,但是这种转换使得您故意朝自己的脚开枪是明目张胆的,而读取与活动成员不同的union成员可能是一个非常微妙的错误。
https://stackoverflow.com/questions/35153015
复制相似问题