2008-09-15 7 views
17

Comment écrivez-vous (en C/C++) une macro qui teste si un type entier (donné en paramètre) est signé ou non signé?Macro pour tester si un type entier est signé ou non

 

     #define is_this_type_signed (my_type) ... 

+1

C et C++ sont deux langues différentes mais connexes. Vous voulez garder cela à l'esprit - les macros sont une excellente solution en C mais elles sont dangereuses et surtout inutiles en C++. Les macros court-circuitent complètement le contrôle de type en C++, juste pour les démarreurs. –

+1

Il y a certaines choses que vous ne pouvez pas faire sans macros. Quoi qu'il en soit, du code C/C++ est nécessaire si vous voulez faire quelque chose de similaire dans un template C++. – botismarius

+1

Pouvez-vous expliquer ce que "certaines choses" ne peuvent pas faire sans macros? –

Répondre

25

Si ce que vous voulez est une macro simple, cela devrait faire l'affaire:

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

Cette réponse a une variable unitialisée; Cela peut ne pas toujours fonctionner. Besoin de changer en: #define is_type_signed (my_type) (((mon_type (0)) - 1) <0) –

+0

Patrick J: En C++, l'original fonctionne correctement en raison de l'initialisation par défaut. Vous avez raison en C, cependant. – Branan

+13

Comment peut-il y avoir une variable non initialisée lorsque les seules variables sont les temporaires 0 et -1? –

39

En C++, utilisez std::numeric_limits<type>::is_signed.

#include <limits> 
std::numeric_limits<int>::is_signed - returns true 
std::numeric_limits<unsigned int>::is_signed - returns false 

Voir http://msdn.microsoft.com/en-us/library/85084kd6(VS.80).aspx.

+1

Pas techniquement une "macro" comme demandé, mais certainement la méthode la plus standard pour un type intégré. –

+1

D'accord, mais les macros doivent être évitées autant que possible en C++ IMO. – ChrisN

+0

D'accord, j'ai voté votre réponse - simplement en la comparant à la réponse acceptée actuellement. –

0

C++, il y a boost :: is_unsigned < T>. Je suis curieux de savoir pourquoi vous en avez besoin, il y a peu de bonnes raisons à mon humble avis.

+0

Je dois calculer la valeur maximale et la valeur minimale pour une variable de type entier, étant donné son type. – botismarius

+0

Vous pouvez utiliser std :: numeric_limits <> :: max() et std :: numeric_limits <> :: min() pour obtenir les valeurs maximum et minimum d'un type. – ChrisN

+1

Si vous le vouliez, pourquoi ne l'avez-vous pas demandé en premier lieu? –

1

Votre exigence est pas exactement le meilleur, mais si vous souhaitez pirater ensemble une définition, une option pourrait être:

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

Cependant, ce n'est pas considéré agréable ou portable par N'importe quel moyen.

1

En fait, je me demandais la même chose plus tôt aujourd'hui. Ce qui suit semble fonctionner:

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

J'ai testé avec:

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

qui imprime:

int is signed 
unsigned int is unsigned 
-1

Vous pouvez le faire mieux avec une fonction de modèle, moins macro sale affaire.

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

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

Forgive la mise en forme ...

J'essayer et voir si cela fonctionne ...

1

En C++, vous pouvez faire:


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

numeric_limits est défini dans l'en-tête < limits>.

+1

Il n'y a rien de tel que typeof() en C++. Mais en C++ 11 il y a decltype (variable), ça fait la chose. – mcv

-1

En C, vous ne pouvez pas écrire une macro qui fonctionne sur des types de types entiers non encore inconnus.

En C++, vous pouvez aussi longtemps que votre type est un type entier fondamental ou un typedef d'un type entier fondamental. Voici ce que vous feriez en C++:

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 
4

Si vous voulez une macro alors cela devrait faire l'affaire:

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

Fondamentalement, jeter -1 à votre type et voir si elle est encore -1 . En C++, vous n'avez pas besoin de macro.Juste #include <limits> et:

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

Althout typeof est pas C++ juridique pour le moment, vous pouvez utiliser à la place déduction de modèle. Voir l'exemple de code ci-dessous:

#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; 
} 

Ce code imprimera

1 0 1 
0

Une approche plus "moderne" est d'utiliser type_traits:

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