Qu'est-ce qu'un cast de type en C/C++? Comment le compilateur vérifie-t-il si un transtypage explicite est nécessaire (et valide)? Compare-t-il l'espace requis pour une valeur? Si j'ai par exemple:
int a;
double b = 15.0;
a = (int) b;
Si je me souviens bien, une valeur double nécessite plus d'espace (était-ce 8 octets?!) Qu'un entier (4 octets). Et la représentation interne des deux est complètement différente (complément sur deux/mantisse). Que se passe-t-il donc en interne? L'exemple ici est assez simple, mais en C/C++ il existe de nombreuses typecasts.
Comment le compilateur sait-il (ou le programmeur) si je peux lancer par exemple FOO à BAR?
Une conversion de type est essentiellement une conversion d'un type à un autre. Il peut être implicite (c'est-à-dire fait automatiquement par le compilateur, peut-être perdre des informations dans le processus) ou explicite (c'est-à-dire spécifié par le développeur dans le code). L'espace occupé par les types est d'importance secondaire. Plus important encore est l'applicabilité (et parfois la convenance) de la conversion.
Il est possible que les conversions implicites perdent des informations, des signes peuvent être perdus/gagnés et un débordement/sous-débordement peut se produire. Le compilateur ne vous protégera pas de ces événements, sauf peut-être par le biais d'un avertissement généré au moment de la compilation. Le découpage peut également se produire lorsqu'un type dérivé est implicitement converti en type de base (par valeur).
Pour les conversions qui peuvent être carrément dangereuses (par exemple, d'une base à un type dérivé), la norme C++ nécessite une conversion explicite. Non seulement cela, mais il offre des transtypages explicites plus restrictifs, tels que static_cast
, dynamic_cast
, reinterpret_cast
, et const_cast
, dont chacun restreint davantage la conversion explicite à un sous-ensemble de conversions possibles, ce qui réduit le risque d'erreurs de diffusion.
Les conversions valides, implicites et explicites sont finalement définies par les normes C/C++, bien qu'en C++, le développeur ait la possibilité d'étendre les conversions pour les types définis par l'utilisateur, implicites et explicites, via l'utilisation de constructeurs et d'opérateurs surchargés (cast) .
Les règles complètes pour lesquelles les lancements sont autorisés par les normes et celles qui ne le sont pas peuvent être assez complexes. J'ai essayé de présenter fidèlement un résumé quelque peu concis de certaines de ces règles dans cette réponse. Si vous êtes vraiment intéressé par ce qui est et n'est pas autorisé, je vous invite fortement à visiter les normes et à lire les sections respectives sur la conversion de type.
Je veux juste mentionner quelque chose que l'on oublie souvent:
Cela peut être important. Par exemple:
#include <iostream>
void change_one_print_other( int& a, const int& b )
{
a = 0;
std::cout << b << "\n";
}
int main(void)
{
int x = 5, y = 5;
change_one_print_other(x, x);
change_one_print_other(y, static_cast<int>(y));
}
Ce casting semble inutile. Mais les regards peuvent être trompeurs .
Faites un petit programme C de votre code et suivez les instructions dans Comment obtenir GCC pour générer le code d'assemblage pour voir comment le le compilateur effectue une conversion de type.
Il existe certains types de transtypages que le compilateur sait faire implicitement - doubler vers int en fait partie. Il supprime simplement la partie décimale. La représentation interne est convertie dans le cadre du processus afin que l'affectation fonctionne correctement.
Notez qu'il existe des valeurs trop grandes pour être converties correctement. Je ne me souviens pas quelles sont les règles pour ce cas; il peut être laissé à la discrétion du compilateur.