2014-12-14 1 views
0

Скажите, что мой код C использует константу RANGEMAX, которая является наибольшей мощностью 10 штук в int. Я могу определить его:Определить (и вычислить) константу C во время компиляции

#include <limits.h> 
#if (INT_MAX < 1) 
#define RANGEMAX ERROR1 
#elif (INT_MAX >= 1) && (INT_MAX < 10) 
#define RANGEMAX 1 
#elif (INT_MAX >= 10) && (INT_MAX < 100) 
#define RANGEMAX 10 
#elif (INT_MAX >= 100) && (INT_MAX < 1000) 
#define RANGEMAX 100 
...    /* well, you get the picture */ 
#elif (INT_MAX >= 10000000000000000) 
#define RANGEMAX ERROR2 
#endif 

Есть более разумный способ делать такие простые вычисления в макро-фазе предварительной обработки?

И поскольку это «простые» вычисления, я предпочитаю решения, которые средний парень, как я, поймет, просто прочитав код.

+1

Многие системы сборки, в том числе config, компилируются и запускают небольшие автономные программы для создания зависящих от машины заголовков для таких констант. – Gene

ответ

3

INT_MAX определено как минимум 32767 (т. Е. 2 ​​^ 15-1). Поскольку подписан протокол int, на практике вам нужно проверить только 2^15-1, 2^31-1 и (теоретически) 2^63-1. Это уменьшит размер вашего блока #if.

+0

2^32-1 -> 2^31-1 – deviantfan

+0

@deviantfan - спасибо, исправлено – abligh

1

С помощью серии испытаний, подтверждающих приблизительный диапазон INT_MAX, можно произвести умножение на 1, 10, 100, 10000, 100000000, 10000000000000000 и т. Д.

Следующие должны работать 10000 <= INT_MAX < power(10,32)

#include <stdio.h> 
#include <limits.h> 

#define F1(x) (1) 
#define F2(x) (((x) >= 10) ? 10 * F1((x)/10): F1(x)) 
#define F3(x) (((x) >= 100) ? 100 * F2((x)/100): F2(x)) 
#define F4(x) (((x) >= 10000) ? 10000 * F3((x)/10000): F3(x)) 
#define F5(x) (((x) >= 100000000) ? 100000000 * F4((x)/100000000): F4(x)) 

#define ITEST (INT_MAX) 

#if ITEST/10000 >= 10000 
    #if ITEST/100000000 >= 100000000 
    #define INT10_MAX (10000000000000000 * F6(ITEST/10000000000000000)) 
    #else 
    #define INT10_MAX (100000000 * F5(ITEST/100000000)) 
    #endif 
#else 
    #define INT10_MAX (10000 * F4(ITEST/10000)) 
#endif 

int main(void) { 
    printf("%d\n", ITEST); 
    printf("%d\n", INT10_MAX); 
    return 0; 
} 

Прагматичный подход мог бы предположить INT_MAX быть power(2,15)-1 или power(2,31)-1, power(2,63)-1. Макро арифметика должна быть осторожна с использованием значений вне 32-битного диапазона.

#if INT_MAX/10000 == 3 
    #define INT10_MAX 10000 
#elif INT_MAX/1000000000 == 2 
    #define INT10_MAX 1000000000 
#elif INT_MAX/1000000000/1000000000 == 9 
    #define INT10_MAX 1000000000000000000 
#else 
    #error Unusual INT_MAX 
#endif