реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Получение предельно допустимых значений переменной, во время работы программы на случай переопределения типа
Dimoza
сообщение Apr 1 2013, 12:05
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 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;

Но компилятор в этом случае выдаёт предупреждение о том, что "превышено максимально допустимое значение", что логично: в процессе вычисления есть промежуточная величина, выходящая за допустимые для данного типа пределы.
Go to the top of the page
 
+Quote Post
msalov
сообщение Apr 1 2013, 13:36
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Можно присваивать ULLONG_MAX (limits.h). Всё лишнее будет отброшено. Подходит только беззнаковым типам. Для знаковых надо сбросить старший бит, а то получится -1.
Или memset(&var, 0xFF, sizeof var).
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 1 2013, 14:28
Сообщение #3


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Dimoza @ Apr 1 2013, 16:05) *
...возможно ли в С/С++...Хорошо если при этом не забыли пробежать по коду и везде поменять. А если забыли?...


вообщето условие перечёркивает вопрос. если си плас плас юзаете по назначению (ООА & ООП) - то и проблем не должно быть по определению (за рамками файла). иначе - менять консерваторию, либо писать на азме.
Go to the top of the page
 
+Quote Post
XVR
сообщение Apr 2 2013, 09:04
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



В С++ можно - там есть специальный include - limits
Код
#include <limits>

typedef signed int MyInt;

MyInt AD_Umax;
AD_Umax = numeric_limits<MyInt>::max();

Go to the top of the page
 
+Quote Post
Dimoza
сообщение Apr 3 2013, 11:16
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 120
Регистрация: 21-08-06
Из: СПб
Пользователь №: 19 701



То что консерватория не по феншую, это я понимаю. В итоге скорее всего перепишу код, чтобы таких заморочек не было.

А за идеи большое спасибо! Всегда интересно, какие "козьи тропы" существуют.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 5 2013, 06:54
Сообщение #6


неотягощённый злом
******

Группа: Свой
Сообщений: 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)


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
neiver
сообщение Apr 5 2013, 10:06
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 5 2013, 10:33
Сообщение #8


неотягощённый злом
******

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



Цитата(neiver @ Apr 5 2013, 14:06) *
Эти шаблоны несложно на макросы переписать, если нужно.
А вы попробуйте! Да так чтобы без привязки к gcc...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
neiver
сообщение Apr 5 2013, 10:54
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 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)
};

Но мне с шаблонами удобнее.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 5 2013, 11:06
Сообщение #10


неотягощённый злом
******

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



Цитата(neiver @ Apr 5 2013, 14:54) *
Это немного не то...
Вы аргументом передаёте тип, а нужно экземпляр этого типа...
Но и так тоже можно выкрутиться (через typedef).
А вообще очень лаконично сделано!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Nixon
сообщение Apr 5 2013, 11:59
Сообщение #11


Гуру
******

Группа: Админы
Сообщений: 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


--------------------
Вам помочь или не мешать?
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 15:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.01464 секунд с 7
ELECTRONIX ©2004-2016