Подтвердить что ты не робот

Макрос, чтобы проверить, подписан ли целочисленный тип или нет.

Как бы вы пишете (в C/С++) макрос, который проверяет, является ли целочисленный тип (заданный как параметр) подписанным или неподписанным?

      #define is_this_type_signed (my_type) ...

4b9b3361

Ответ 1

Если вам нужен простой макрос, это должно сделать трюк:

#define is_type_signed(my_type) (((my_type)-1) < 0)

Ответ 3

Если вам нужен макрос, то это должно сделать трюк:

#define IS_SIGNED( T ) (((T)-1)<0)

В принципе, приведите -1 к вашему типу и посмотрите, все ли он -1. В С++ вам не нужен макрос. Просто #include <limits> и:

bool my_type_is_signed = std::numeric_limits<my_type>::is_signed;

Ответ 4

Ваше требование не является лучшим, но если вы хотите взломать определение, одним из вариантов может быть:

#define is_numeric_type_signed(typ) ( (((typ)0 - (typ)1)<(typ)0) && (((typ)0 - (typ)1) < (typ)1) )

Однако это не считается приятным или переносимым любыми способами.

Ответ 5

На самом деле я сегодня просто задавался вопросом о том же. Кажется, что работает следующее:

#define is_signed(t)    ( ((t)-1) < 0 )

Я тестировал с помощью:

#include <stdio.h>

#define is_signed(t)    ( ((t)-1) < 0 )
#define psigned(t) printf( #t " is %s\n", is_signed(t) ? "signed" : "unsigned" );

int
main(void)
{
    psigned( int );
    psigned( unsigned int );
}

который печатает:

int is signed
unsigned int is unsigned

Ответ 6

В С++ вы можете:


bool is_signed = std::numeric_limits<typeof(some_integer_variable)>::is_signed;

numeric_limits определяется в заголовке <limits> .

Ответ 7

Althout typeof не является законным С++ на данный момент, вы можете использовать вычет шаблона. См. Пример кода ниже:

#include <iostream>
#include <limits>

template <typename T>
bool is_signed(const T& t)
{
  return std::numeric_limits<T>::is_signed;
}

int main()
{
  std::cout << 
    is_signed(1) << " " << 
    is_signed((unsigned char) 0) << " " << 
    is_signed((signed char) 0) << std::endl;
}

Этот код напечатает

  1 0 1

Ответ 8

Для С++ существует boost:: is_unsigned <T> . Мне любопытно, зачем вам это нужно, хотя есть несколько веских причин ИМХО.

Ответ 9

Более "современный" подход заключается в использовании type_traits:

#include <type_traits>
#include <iostream>
int main()
{
    std::cout << ( std::is_signed<int>::value ? "Signed" : "Unsigned") <<std::endl;
}

Ответ 10

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

    template <typename T>
        bool IsSignedType()
        {
           // A lot of assumptions on T here
           T instanceAsOne = 1;

           if (-instanceAsOne > 0)
           {
               return true;
           }
           else
           {
               return false;
           }
}

Простите форматирование...

Я бы попробовал это и посмотрел, работает ли он...

Ответ 11

В C вы не можете написать макрос, который работает с пока неизвестным typedef основных целых типов.

В С++ вы можете до тех пор, пока ваш тип представляет собой фундаментальный целочисленный тип или typedef основного целочисленного типа. Вот что вы бы сделали в С++:

template <typename T>
struct is_signed_integer
{
    static const bool value = false;
};

template <>
struct is_signed_integer<int>
{
    static const bool value = true;
};

template <>
struct is_signed_integer<short>
{
    static const bool value = true;
};

template <>
struct is_signed_integer<signed char>
{
    static const bool value = true;
};

template <>
struct is_signed_integer<long>
{
    static const bool value = true;
};

// assuming your C++ compiler supports 'long long'...
template <>
struct is_signed_integer<long long>
{
    static const bool value = true;
};

#define is_this_type_signed(my_type) is_signed_integer<my_type>::value