2016-08-04 5 views
0

Я получил программузначения Хранить в 64 разрядное целое число в C

#include <stdint.h> 
#include <stdio.h> 

int main(void) 
{ 

int i; 
int x = 128; 
int y = 128; 
int z = 2; 
int32_t coordinates = x | (y << 12) | (z << 16); 

fprintf(stdout, "x = %d\n", (coordinates & 0xFF)); 
fprintf(stdout, "y = %d\n", ((coordinates >> 8) & 0xFF)); 
fprintf(stdout, "z = %d\n", ((coordinates >> 16) & 0xFF)); 
} 

Это хранит x,y,z в 32-разрядном регистре, но ее успешное ТОЛЬКО для { (x,y,z)< 256}. Если я хочу, чтобы это было возможно для x,y,z, чтобы получить значения 2^10 (1024) (так (x,y,z)<1024), как это может произойти? Я знаю, что я должен использовать 64-битный регистр (?), Но я застрял на этом, потому что что-то происходит со сменой.

Любые идеи?

+1

Вы должны использовать 64 бит переменной а и ... просто изменить как сдвиг и маски. 1024 - это 10 бит, а затем сдвиг на 10, а затем на 20 и маска с 0x3FF –

+1

. В 'stdint.h' могут быть *' int64_t/uint64_t' (но они не являются обязательными). –

+0

Ваш код вызывает неопределенное поведение на платформах с 'int', например. 16 бит. В общем, это плохая идея сдвинуть знаковые целые числа, если вы не можете гарантировать, что эти сдвиги никогда не вызовут неопределенное поведение. Это означает, что следует избегать определенных комбинаций значений/сдвигов. – Olaf

ответ

1
  1. Вместо того чтобы использовать подписали типов, используйте неподписанные типов. Гораздо меньше проблем. @Olaf

  2. Этот код позволяет x иметь 12-битный диапазон перед встречей с y. Он позволяет y иметь 4-разрядный (16 - 12) диапазон перед встречей с z. У этого есть проблемы с 16-битным int/unsigned.

    int32_t coordinates = x | (y << 12) | (z << 16); 
    

Чтобы разрешить x,y,z иметь 10-битный диапазон, сдвиг y на 10 и на 10 z + 10.

uint32_t coordinates = x | ((uint32_t)y << 10) | ((uint32_t)z << 20); 

Для точных значений:
(обязательно использовать соответствующую для печати спецификатора тоже.)

#include <inttypes.h> 
... 
fprintf(stdout, "x = %" PRIu32 "\n", (coordinates & 0x3FF)); 
fprintf(stdout, "y = %" PRIu32 "\n", ((coordinates >> 10) & 0x3FF)); 
fprintf(stdout, "z = %" PRIu32 "\n", ((coordinates >> 20) & 0x3FF)); 
+0

С unsigned int 32 бит, будет ли проблема при отправке с MPI? Или я должен предпочесть подписанный? – BillG

+0

@BillG В этом случае код мог бы использовать 'int32_t', а также с' uint32_t', поскольку два верхних бита не используются. Используйте 'uint32_t' как часть вашего [MPI] (https://en.wikipedia.org/wiki/Message_Passing_Interface), если это возможно, иначе измените значение на' int32_t'. Я подозреваю, что 'int32_t' пользуется преимуществом, но мне нужно будет больше узнать о коде для лучшего ответа. – chux

1

Если у вас есть 3 поля 10 бита, те будут помещаться в 32 битном междунаре , Вы можете сделать это следующим образом:

int32_t coordinates = (int32_t)(x & 0x3ff) | 
         ((int32_t)(y & 0x3ff) << 10) | 
         ((int32_t(z & 0x3ff) << 20); 

Вы первым выполнить побитовое И 0x3ff с каждым номером, чтобы убедиться, что вы получите только самые низкие 10 бит. Затем результат преобразуется в тип результата, чтобы убедиться, что при смещении значения он не сдвигается слишком далеко для промежуточных значений. Тогда каждое значение представляет собой места с 10-битным смещением через сдвиги.

Тогда вы можете прочитать их обратно следующим образом:

fprintf(stdout, "x = %d\n", (coordinates & 0x3FF)); 
fprintf(stdout, "y = %d\n", ((coordinates >> 10) & 0x3FF)); 
fprintf(stdout, "z = %d\n", ((coordinates >> 20) & 0x3FF));