57 votes

Comment dois-je m'adresser pour "au moins" une de la taille d'un int en C

La situation:

J'ai une application écrite en C qui demande beaucoup de ressources, et conçu pour être portable. Je veux permettre au compilateur de sélectionner la manière la plus rapide int taille pour l'architecture, à condition qu'il soit au moins 32 bits.

Est-il possible de sélectionner une taille de "au moins" 32 bits, ou le compilateur d'optimiser ces sortes de choses m'automatiquement?

92voto

Drew McGowen Points 7528

L'en-tête standard stdint.h offre les types d' int_leastN_t et uint_leastN_tN est de 8, 16, 32, et 64 (et probablement d'autres, mais elles ne sont pas nécessaires). Ce sont des standards de C99.

Il fournit aussi "rapide" solutions de rechange", aka int_fastN_t et uint_fastN_t, avec les mêmes valeurs de N.

Donc, dans votre cas, vous pouvez utiliser int_least32_t ou int_fast32_t.

20voto

supercat Points 25534

Comme d'autres l'ont noté, la norme de fichiers définissent int_fast32_t, int_least32_t, uint_fast32_t, uint_least32_t qui devrait susceptible de se comporter comme vous le souhaitez, mais ces types doivent être utilisés avec une extrême prudence. En raison de entier les règles de la promotion, il n'existe aucun moyen pour du code C pour éviter l'utilisation de types d' int et unsigned int. En outre, les littéraux entiers ne peuvent pas toujours être des types que l'on attend. Une comparaison entre un int_fast32_T et les littéraux 0xABCD1234 ou 12345u, par exemple, peuvent être effectués que soit signé ou non signé, selon qu' int est de 16, 32 ou 64 bits. De même, si l' n est 32 bits ou plus, le sens de l' n &= ~0x8000; serait différent sur 16 bits de la machine sur la base d'une plus grande.

La norme n'a jamais été particulièrement conçu pour faciliter l'écriture de code qui se soucie entier tailles, mais néanmoins de travail compatible sur le matériel avec des tailles différentes. Des Types comme int_fast32_t le rendre facile d'écrire du code qui semble comme il devrait être portable, mais peut encourager la complaisance à l'égard de tous les méchants petits pièges cachés dans la langue.

10voto

Manu343726 Points 8803

Cette question a été étiquetée comme C++ trop, voici donc une solution pour modèle la métaprogrammation les amateurs comme moi.

Exigences

  • Un typelist type, nommé list ici.
  • Un Haskell-comme filter metafunction.
  • Un head metafunction pour obtenir le premier élément d'un typelist.

Le code

Cette solution automatise la solution retenue (ce Qui est juste "aller à l' stdint.h et de choisir le plus adéquat pour vous"). Ce travail pourrait être fait par le compilateur, ne pourrait-elle pas?

D'abord la liste de toutes les plate-forme spécifique plus rapide des types d'entiers a déclaré à l' <cstdint>:

using integer_types = list<std::int_fast8_t,std::int_fast16_t,
                           std::int_fast32_t,std::int_fast64_t>;

Notez que la liste est classée par l'augmentation de nombre entier de taille.
Définir un filtrage du prédicat. Dans notre cas, la taille doit être inférieure à la taille spécifiée par l'utilisateur (nom, il SIZE):

template<typename T>
using f = std::integral_constant<bool,sizeof(T)*CHAR_BITS <= SIZE>;

Et puis filtrer la liste des types d'entiers et d'obtenir le premier élément de la suite:

using best_integer_t = head<filter<f,integer_types>>;

Résumé de la solution

template<std::size_t SIZE>
struct fastest_integer_impl
{
    //Guard for the case the user specified less than one byte size:
    static constexpr const std::size_t size = SIZE >= CHAR_BITS ? size : CHAR_BITS;

    using integer_types = list<std::int_fast8_t,std::int_fast16_t,
                               std::int_fast32_t,std::int_fast64_t>;

    template<typename T>
    using f = std::integral_constant<bool,sizeof(T)*CHAR_BITS <= size>;

    using type = head<filter<f,integer_types>>;
};

template<std::size_t SIZE>
using fastest_integer = typename fastest_integer_impl<SIZE>::type;

-5voto

sudhakar Points 1

plus rapide => aligner à l'architecture, à l'aide de pragma pack. Sans cela, dans le cas où la mémoire n'est pas aligné, il faudrait plus d'un accès à la mémoire.

min 32 => utiliser le spécificateur de type int - assez. Cela garantit 32 bits de linux dans toutes les architectures à ma connaissance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X