Vous pouvez éviter des moulages avec des conversions implicites:
uint32_t pack_helper(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3) {
return c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
}
uint32_t pack(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3) {
return pack_helper(c0, c1, c2, c3);
}
L'idée est que vous voyez, plutôt que « pour chaque paramètre, convertir correctement, shift « convertir tous les paramètres correctement Maj et les combiner. » et combinez-le ". Pas grand-chose, cependant.
Puis:
template <int N>
uint8_t unpack_u(uint32_t packed) {
// cast to avoid potential warnings for implicit narrowing conversion
return static_cast<uint8_t>(packed >> (N*8));
}
template <int N>
int8_t unpack_s(uint32_t packed) {
uint8_t r = unpack_u<N>(packed);
return (r <= 127 ? r : r - 256); // thanks to caf
}
int main() {
uint32_t x = pack(4,5,6,-7);
std::cout << (int)unpack_u<0>(x) << "\n";
std::cout << (int)unpack_s<1>(x) << "\n";
std::cout << (int)unpack_u<3>(x) << "\n";
std::cout << (int)unpack_s<3>(x) << "\n";
}
Sortie:
4
5
249
-7
C'est aussi portable que les uint32_t
, uint8_t
et int8_t
types. Aucun d'entre eux n'est requis dans C99, et l'en-tête stdint.h n'est pas défini en C++ ou C89. Si les types existent et répondent aux exigences C99, cependant, le code fonctionnera. Bien sûr, en C, les fonctions de décompression nécessiteraient un paramètre de fonction au lieu d'un paramètre de modèle. Vous préférerez peut-être aussi en C++ si vous voulez écrire des boucles courtes pour le déballage. Pour traiter le fait que les types sont facultatifs, vous pouvez utiliser uint_least32_t
, ce qui est requis dans C99. De manière similaire, uint_least8_t
et int_least8_t
. Vous devrez changer le code de pack_helper et unpack_u:
uint_least32_t mask(uint_least32_t x) { return x & 0xFF; }
uint_least32_t pack_helper(uint_least32_t c0, uint_least32_t c1, uint_least32_t c2, uint_least32_t c3) {
return mask(c0) | (mask(c1) << 8) | (mask(c2) << 16) | (mask(c3) << 24);
}
template <int N>
uint_least8_t unpack_u(uint_least32_t packed) {
// cast to avoid potential warnings for implicit narrowing conversion
return static_cast<uint_least8_t>(mask(packed >> (N*8)));
}
Pour être honnête, il est peu probable d'être la peine - les chances sont le reste de votre application est écrite sur l'hypothèse que int8_t
etc existent. C'est une implémentation rare qui n'a pas un type de complément 8 bits et 32 bits 2.
En C et C++, un 'char' _always_ a une taille d'un octet. Un octet peut ne pas être huit bits. –
+1: Pour diviser en deux fonctions et utiliser la fonction au lieu de la macro. C'est un cas idéal pour avoir une fonction en ligne. – Arun
Je suis curieux de savoir pourquoi vous adoptez une fonction C++ (fonctions inline) mais en condamne une autre (opérateurs de cast améliorés) .... Les conversions de style C sont déconseillées pour une raison. Sinon +1. –