|
|
  |
Получение предельно допустимых значений переменной, во время работы программы на случай переопределения типа |
|
|
|
Apr 1 2013, 12:05
|
Частый гость
 
Группа: Свой
Сообщений: 120
Регистрация: 21-08-06
Из: СПб
Пользователь №: 19 701

|
Здравствуйте. Подскажите, возможно ли в С/С++ красиво реализовать следующее: Есть некая переменная, которой во время работы программы хочется присвоить максимально (минимально) допустимое значение. Если мы например решили, что переменная типа signed char, то ясное дело, можно просто присваивать +127 или -128. Но если вдруг по каким либо причинам тип изменили на signed int, то нужны уже другие значения, +32767 и -32768. Хорошо если при этом не забыли пробежать по коду и везде поменять. А если забыли? Как бы это покрасивше автоматизировать? Вроде бы корректный путь написать что-то вроде: CODE signed int AD_Umax; AD_Umax = (1<<(sizeof(AD_Umax)*8-1))-1; Но компилятор в этом случае выдаёт предупреждение о том, что "превышено максимально допустимое значение", что логично: в процессе вычисления есть промежуточная величина, выходящая за допустимые для данного типа пределы.
|
|
|
|
|
Apr 5 2013, 06:54
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Дима, привет! Только это смог изобразить, поэтому смену знаковости аргумента не отловит : Код #define MAX_UNSIGNED(X) \ ((sizeof(X) == 1)? 0xffU : \ (sizeof(X) == 2)? 0xffffU : \ (sizeof(X) == 4)? 0xffffffffUL : 0U)
#define MAX_SIGNED(X) \ ((sizeof(X) == 1)? 0x7f : \ (sizeof(X) == 2)? 0x7fff : \ (sizeof(X) == 4)? 0x7fffffffL : 0L)
#define MIN_UNSIGNED(X) 0U
#define MIN_SIGNED(X) \ ((sizeof(X) == 1)? -128 : \ (sizeof(X) == 2)? -32768 : \ (sizeof(X) == 4)? -2147483648L : 0L) Ещё немного подумал и нашёл решение для gcc! Код #define IS_UNSIGNED(X)\ ({ \ const typeof(X) __x = 0; \ const typeof(X) __y = __x-1; \ (__y>0); \ })
#define MIN_OF_TYPE(X) ((IS_UNSIGNED(X))? MIN_UNSIGNED(X) : MIN_SIGNED(X)) #define MAX_OF_TYPE(X) ((IS_UNSIGNED(X))? MAX_UNSIGNED(X) : MAX_SIGNED(X)) И ещё немного подумал и для gcc написал ещё проще: Код #define MAX_OF_TYPE(X) \ ((__builtin_types_compatible_p(typeof(X), int8_t))? (int8_t)0x7f : \ (__builtin_types_compatible_p(typeof(X), int16_t))? (int16_t)0x7fff : \ (__builtin_types_compatible_p(typeof(X), int32_t))? (int32_t)0x7fffffff : \ (__builtin_types_compatible_p(typeof(X), uint8_t))? (uint8_t)0xff : \ (__builtin_types_compatible_p(typeof(X), uint16_t))? (uint16_t)0xffff : \ (__builtin_types_compatible_p(typeof(X), uint32_t))? (uint32_t)0xffffffff : 0)
#define MIN_OF_TYPE(X) \ ((__builtin_types_compatible_p(typeof(X), int8_t))? (int8_t)0x80 : \ (__builtin_types_compatible_p(typeof(X), int16_t))? (int16_t)0x8000 : \ (__builtin_types_compatible_p(typeof(X), int32_t))? (int32_t)0x80000000 : \ (__builtin_types_compatible_p(typeof(X), uint8_t))? (uint8_t)0x00 : \ (__builtin_types_compatible_p(typeof(X), uint16_t))? (uint16_t)0x0000 : \ (__builtin_types_compatible_p(typeof(X), uint32_t))? (uint32_t)0x00000000 : 0)
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Apr 5 2013, 10:06
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Я для определения предельных значений типов пользуюсь такими С++ шаблонами: Код template<class T, T IntegralTypeCheck=T(0)> struct IsSigned { enum{value = T(-1) < T(0)}; };
template<class T> struct MinValue { static const T value = IsSigned<T>::value ? ( T(1) << (sizeof(T)*8 - 1)) : 0; };
template<class T> struct MaxValue { static const T value = ~MinValue<T>::value; }; Работает, естественно, на платформах где в байте 8 бит и с отрицательными числами в дополнительном коде. Эти шаблоны несложно на макросы переписать, если нужно. А пользоваться ими примерно так: Код cout << "Min int =\t" << MinValue<int>::value << "\tMax int = " << MaxValue<int>::value << endl; cout << "Min unsigned =\t" << MinValue<unsigned>::value << "\tMax unsigned = " << MaxValue<unsigned>::value << endl; cout << "Min long long =\t" << MinValue<long long>::value << "\tMax long long = " << MaxValue<long long>::value << endl; cout << "Min char =\t" << MinValue<char>::value << "\tMax char = " << MaxValue<char>::value << endl; cout << "Min short =\t" << MinValue<short>::value << "\tMax short = " << MaxValue<short>::value << endl; cout << "Min unsigned short =\t" << MinValue<unsigned short>::value << "\tMax unsigned short = " << MaxValue<unsigned short>::value << endl;
Сообщение отредактировал neiver - Apr 5 2013, 10:11
|
|
|
|
|
Apr 5 2013, 10:54
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Цитата(demiurg_spb @ Apr 5 2013, 14:33)  А вы попробуйте! Да так чтобы без привязки к gcc... Попробовал. Получилось. Работает. Код #define __IS_SIGNED(TYPE) ((TYPE)(-1) < (TYPE)(0)) #define IS_SIGNED(TYPE) __IS_SIGNED(TYPE) #define __MIN_VALUE(TYPE) (IS_SIGNED(TYPE) ? ( (TYPE)(1) << (sizeof(TYPE)*8 - 1)) : 0) #define MIN_VALUE(TYPE) __MIN_VALUE(TYPE) #define __MAX_VALUE(TYPE) (~MIN_VALUE(TYPE)) #define MAX_VALUE(TYPE) __MAX_VALUE(TYPE) Можно даже вот так писать: Код #define MY_TYPE int enum Foo { Max = MAX_VALUE(MY_TYPE) }; Но мне с шаблонами удобнее.
|
|
|
|
|
Apr 5 2013, 11:06
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(neiver @ Apr 5 2013, 14:54)  Это немного не то... Вы аргументом передаёте тип, а нужно экземпляр этого типа... Но и так тоже можно выкрутиться (через typedef). А вообще очень лаконично сделано!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Apr 5 2013, 11:59
|
Гуру
     
Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48

|
Немножко не совсем определение максимального и минимального значения, но близко Получаю тип переменной по имени на этапе компиляции следующим образом: Код template<class T, class U> struct IsSame { char d; }; template<class T> struct IsSame<T, T> { char d[2]; }; template<class T, class U> IsSame<T, U> test(const U&);
#define IS_SAME_TYPE(type, var) (sizeof(test<type>(var)) == sizeof(IsSame<int, int>))
#define GET_STD_TYPE(var) (IS_SAME_TYPE(uint8_t, var) ? T_U08 : \ (IS_SAME_TYPE(int8_t, var) ? T_S08 : \ (IS_SAME_TYPE(uint16_t, var) ? T_U16 : \ (IS_SAME_TYPE(int16_t, var) ? T_S16 : \ (IS_SAME_TYPE(uint32_t, var) ? T_U32 : \ (IS_SAME_TYPE(int32_t, var) ? T_S32 : \ (IS_SAME_TYPE(uint64_t, var) ? T_U32 : \ (IS_SAME_TYPE(int64_t, var) ? T_S32 : \ (IS_SAME_TYPE(char*, var) ? T_STR : \ (IS_SAME_TYPE(float, var) ? T_FLOAT : \ (IS_SAME_TYPE(double, var) ? T_DOUBLE : \ T_NONE))))))))))) По типу сделать определение максимального и минимального значения уже проще будет
gettype.rar ( 806 байт )
Кол-во скачиваний: 62
--------------------
Вам помочь или не мешать?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|