Перейти к содержанию
    

Получение предельно допустимых значений переменной

Здравствуйте. Подскажите, возможно ли в С/С++ красиво реализовать следующее:

 

Есть некая переменная, которой во время работы программы хочется присвоить максимально (минимально) допустимое значение. Если мы например решили, что переменная типа signed char, то ясное дело, можно просто присваивать +127 или -128. Но если вдруг по каким либо причинам тип изменили на signed int, то нужны уже другие значения, +32767 и -32768. Хорошо если при этом не забыли пробежать по коду и везде поменять. А если забыли? Как бы это покрасивше автоматизировать? Вроде бы корректный путь написать что-то вроде:

signed int AD_Umax;
AD_Umax =  (1<<(sizeof(AD_Umax)*8-1))-1;

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно присваивать ULLONG_MAX (limits.h). Всё лишнее будет отброшено. Подходит только беззнаковым типам. Для знаковых надо сбросить старший бит, а то получится -1.

Или memset(&var, 0xFF, sizeof var).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...возможно ли в С/С++...Хорошо если при этом не забыли пробежать по коду и везде поменять. А если забыли?...

 

вообщето условие перечёркивает вопрос. если си плас плас юзаете по назначению (ООА & ООП) - то и проблем не должно быть по определению (за рамками файла). иначе - менять консерваторию, либо писать на азме.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

#include <limits>

typedef signed int MyInt;

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

А за идеи большое спасибо! Всегда интересно, какие "козьи тропы" существуют.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дима, привет!

Только это смог изобразить, поэтому смену знаковости аргумента не отловит :

#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)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я для определения предельных значений типов пользуюсь такими С++ шаблонами:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Эти шаблоны несложно на макросы переписать, если нужно.
А вы попробуйте! Да так чтобы без привязки к gcc...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вы попробуйте! Да так чтобы без привязки к 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)
};

Но мне с шаблонами удобнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это немного не то...

Вы аргументом передаёте тип, а нужно экземпляр этого типа...

Но и так тоже можно выкрутиться (через typedef).

А вообще очень лаконично сделано!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немножко не совсем определение максимального и минимального значения, но близко

 

Получаю тип переменной по имени на этапе компиляции следующим образом:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...