Как сохранить 64-битное целое число в двух 32-битных целых и преобразовать обратно
Я почти уверен, что это просто вопрос о побитовых операциях, но я не совсем уверен, что именно я должен делать, и все поиски возвращают "64 бит против 32 бит".
8 ответов
Упаковка:
u32 x, y;
u64 v = ((u64)x) << 32 | y;
распаковать:
x = (u32)((v & 0xFFFFFFFF00000000LL) >> 32);
y = (u32)(v & 0xFFFFFFFFLL);
Или это, если вам не интересно, что означают два 32-битных числа:
u32 x[2];
u64 z;
memcpy(x,&z,sizeof(z));
memcpy(&z,x,sizeof(z));
Используйте объединение и избавьтесь от битовых операций:
<stdint.h> // for int32_t, int64_t
union {
int64_t big;
struct {
int32_t x;
int32_t y;
};
};
assert(&y == &x + sizeof(x));
просто как тот. большой состоит из х и у.
Я не знаю, лучше ли это, чем решения union или memcpy, но я должен был распаковать / упаковать 64-битные целые числа со знаком и не хотел ничего маскировать или сдвигать, поэтому я просто обработал 64-битное значение как два 32-битные значения и назначить их напрямую так:
#include <stdio.h>
#include <stdint.h>
void repack(int64_t in)
{
int32_t a, b;
printf("input: %016llx\n", (long long int) in);
a = ((int32_t *) &in)[0];
b = ((int32_t *) &in)[1];
printf("unpacked: %08x %08x\n", b, a);
((int32_t *) &in)[0] = a;
((int32_t *) &in)[1] = b;
printf("repacked: %016llx\n\n", (long long int) in);
}
Основной метод заключается в следующем:
uint64_t int64;
uint32_t int32_1, int32_2;
int32_1 = int64 & 0xFFFFFFFF;
int32_2 = (int64 & (0xFFFFFFFF << 32) ) >> 32;
// ...
int64 = int32_1 | (int32_2 << 32);
Обратите внимание, что ваши целые числа должны быть без знака; или операции не определены.
Вкратце от user204847 и user121747 , без использования приведения в стиле C:
Переменные:
int64_t combined;
int32_t upper,lower;
int64_t->int32_t
upper = static_cast<int32_t>(combined >> 32);
lower = static_cast<int32_t>(combined);
int32_t->int64_t
combined = (static_cast<int64_t>(upper)) << 32 | lower;
Не уверен, что этот способ хорош для переносимости или других, но я использую...
#include <stdio.h>
#include <stdint.h>
typedef enum {false, true} bool;
#ifndef UINT32_WIDTH
#define UINT32_WIDTH 32 // defined in stdint.h, but compiler error ??
#endif
typedef struct{
struct{ // anonymous struct
uint32_t x;
uint32_t y;
};}ts_point;
typedef struct{
struct{ // anonymous struct
uint32_t line;
uint32_t column;
};}ts_position;
bool is_little_endian()
{
uint8_t n = 1;
return *(char *)&n == 1;
}
int main(void)
{
uint32_t x, y;
uint64_t packed;
ts_point *point; // struct offers a "mask" to retreive data
ts_position *position; // in an ordered and comprehensive way.
x = -12;
y = -23;
printf("at start: x = %i | y = %i\n", x, y);
if (is_little_endian()){
packed = (uint64_t)y << UINT32_WIDTH | (uint64_t)x;
}else{
packed = (uint64_t)x << UINT32_WIDTH | (uint64_t)y;
}
printf("packed: position = %llu\n", packed);
point = (ts_point*)&packed;
printf("unpacked: x = %i | y = %i\n", point->x, point->y); // access via pointer
position = (ts_position*)&packed;
printf("unpacked: line = %i | column = %i\n", position->line, position->column);
return 0;
}
Мне нравится, как я это делаю, так как это предлагает большую готовность и может быть применено разными способами, т.е. 02x32, 04x16, 08x08 и т. д. Я новичок в C, поэтому не стесняйтесь критиковать мой код и способ его выполнения... спасибо
long x = 0xFEDCBA9876543210;
cout << hex << "0x" << x << endl;
int a = x ;
cout << hex << "0x" << a << endl;
int b = (x >> 32);
cout << hex << "0x" << b << endl;