Dimoza 0 1 апреля, 2013 Опубликовано 1 апреля, 2013 · Жалоба Здравствуйте. Подскажите, возможно ли в С/С++ красиво реализовать следующее: Есть некая переменная, которой во время работы программы хочется присвоить максимально (минимально) допустимое значение. Если мы например решили, что переменная типа signed char, то ясное дело, можно просто присваивать +127 или -128. Но если вдруг по каким либо причинам тип изменили на signed int, то нужны уже другие значения, +32767 и -32768. Хорошо если при этом не забыли пробежать по коду и везде поменять. А если забыли? Как бы это покрасивше автоматизировать? Вроде бы корректный путь написать что-то вроде: signed int AD_Umax; AD_Umax = (1<<(sizeof(AD_Umax)*8-1))-1; Но компилятор в этом случае выдаёт предупреждение о том, что "превышено максимально допустимое значение", что логично: в процессе вычисления есть промежуточная величина, выходящая за допустимые для данного типа пределы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
msalov 0 1 апреля, 2013 Опубликовано 1 апреля, 2013 · Жалоба Можно присваивать ULLONG_MAX (limits.h). Всё лишнее будет отброшено. Подходит только беззнаковым типам. Для знаковых надо сбросить старший бит, а то получится -1. Или memset(&var, 0xFF, sizeof var). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 1 апреля, 2013 Опубликовано 1 апреля, 2013 · Жалоба ...возможно ли в С/С++...Хорошо если при этом не забыли пробежать по коду и везде поменять. А если забыли?... вообщето условие перечёркивает вопрос. если си плас плас юзаете по назначению (ООА & ООП) - то и проблем не должно быть по определению (за рамками файла). иначе - менять консерваторию, либо писать на азме. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 2 апреля, 2013 Опубликовано 2 апреля, 2013 · Жалоба В С++ можно - там есть специальный include - limits #include <limits> typedef signed int MyInt; MyInt AD_Umax; AD_Umax = numeric_limits<MyInt>::max(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimoza 0 3 апреля, 2013 Опубликовано 3 апреля, 2013 · Жалоба То что консерватория не по феншую, это я понимаю. В итоге скорее всего перепишу код, чтобы таких заморочек не было. А за идеи большое спасибо! Всегда интересно, какие "козьи тропы" существуют. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 5 апреля, 2013 Опубликовано 5 апреля, 2013 · Жалоба Дима, привет! Только это смог изобразить, поэтому смену знаковости аргумента не отловит : #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) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 5 апреля, 2013 Опубликовано 5 апреля, 2013 (изменено) · Жалоба Я для определения предельных значений типов пользуюсь такими С++ шаблонами: 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; Изменено 5 апреля, 2013 пользователем neiver Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 5 апреля, 2013 Опубликовано 5 апреля, 2013 · Жалоба Эти шаблоны несложно на макросы переписать, если нужно.А вы попробуйте! Да так чтобы без привязки к gcc... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 5 апреля, 2013 Опубликовано 5 апреля, 2013 · Жалоба А вы попробуйте! Да так чтобы без привязки к 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) }; Но мне с шаблонами удобнее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 5 апреля, 2013 Опубликовано 5 апреля, 2013 · Жалоба Это немного не то... Вы аргументом передаёте тип, а нужно экземпляр этого типа... Но и так тоже можно выкрутиться (через typedef). А вообще очень лаконично сделано! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Nixon 3 5 апреля, 2013 Опубликовано 5 апреля, 2013 · Жалоба Немножко не совсем определение максимального и минимального значения, но близко Получаю тип переменной по имени на этапе компиляции следующим образом: 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться