2017-01-21 5 views
-3

Отредактировано: «Мне известно, что я не могу использовать sizeof() в препроцессоре. Я изучаю модификацию своего кода.Как использовать препроцессор C для генерации шестнадцатеричного литерала с переменной величиной (зависит от операционной системы)?

У меня есть C код, который использует шестнадцатеричные значения (хранится в переменной типа unsigned int):

0x0000'0000'0000'0001 (64-bit/8 Byte system, 15 0's) 
    0x0000'0001   (32-bit/4 Byte system, 7 0's) 
    0x0001    (16-bit/2 Byte system, 3 0's) 
    0x01     (8-bit /1 Byte system, 1 0's) 

в зависимости от того, как операционная система решает представлять unsigned int (я знаю, что большинство ОС дону 't представляют их как 64'b значения, но несут со мной). Я хотел бы сгенерировать объект-макрос, который принимает одно из четырех указанных выше шестнадцатеричных значений, в зависимости от того, как ОС решает реализовать unsigned int.

Простой (мертвая Reckon) способ сделать это состоит в использовании серии IF-другого заявление:

#define SYS_UINT_TYPE sizeof(unsigned int) 
    #if SYS_UINT_TYPE == 8 
      #define DEFAULT_MASK 0x0000000000000001 
    #elif SYS_UINT_TYPE == 4 
      #define DEFAULT_MASK 0x00000001 
    ... 
    #endif 

Но мне было интересно, если есть способ использовать ## (C Конкатенацию Оператору), чтобы связать правильное число 0, чтобы сгенерировать правильное значение макрорасширения DEFAULT_MASK. Я знаю, что для системы байтов B число 0, которое должно быть объединено с текстовым литералом 0x, равно 2B-1, но не является такой вещью, как директива препроцессора For-loop.

Фактически это сработает, чтобы уменьшить размер #if ... #elif ... #endif, который я должен был напечатать.

+3

Объявите свой литерал как неподписанный int и присвойте ему значение '1' (даже не нужно' 0x' перед ним). Вуаля! Готово. Это будет подходящий размер для unsigned int на любых платформах, на которых вы его компилируете. Ни одного «# if» в поле зрения. –

+0

Это будет работать, Кен. Благодарю. Остается ли в этом вопросе задать вопрос о том, как (если возможно) выполнить ряд конпрограмм препроцессора? –

+0

В * объеме этого вопроса *? Нет. Это совершенно отдельный вопрос, не связанный с этим. Сначала найдите здесь, чтобы узнать, было ли это ранее задано (и старайтесь усердно, потому что я подозреваю, что это так), и если он не создал, то задайте новый вопрос и спросите. –

ответ

0

um все это 0x01 Право? они являются буквальным, так что они будут ИНТ размера, если они вписываются в междунар ...

когда маска делается МДР будут выстроены с LSB ...

убедить себя в этом с:

printf("%lld",(long long) 0x01 | (long) 0x01 | (int) 0x01 | (short) 0x01 | (char) 0x01);

если это выстроено с наиболее значащим битом, то это будет в конечном итоге что-то вроде:

0x01 00 00 00 00 00 00 00 
      0x 01 00 00 00 
      0x 01 00 00 00 
       0x 00 01 00 
        0x 01 
------------------------- all of this | or'd together 
0x01 00 00 00 01 00 01 01 

, но вместо этого он только один (0x01).

все это происходит с помощью магии целого продвижения, где меньших размеры проложенных быть одинаковым значением в большем размере хранения ...

вещи запутаются с подписанными значениями и негативами ... частично потому что правила целочисленного продвижения более сложны.

+2

Спасибо. Я думаю, что это случай, когда я слишком усложнил решение проблемы (как заметил Кэн Уайт). Один из тех моментов «духа». –