Pourquoi ne puis-je pas static_cast entre char et unsigned char *?
Apparemment, le compilateur considère être sans rapport avec les types et donc reinterpret_cast
est nécessaire. Pourquoi est-ce la règle?
- Je prends le SHA-1 hash d'une chaîne de caractères.
c_str()
renvoie uneconst char *
et le SHA-1 fonction prend unconst unsigned char *
comme argument. - Et qu'attendez-vous d'arriver si cette chaîne contient caractère négatif des valeurs?
- J'attends une valeur négative,
c
pour devenirc + 256
, comme c'est la norme dans la conversion d'un octet signé pour un unsigned un. Honnêtement, je suis juste de faire la conversion pour calculer une valeur de hachage. Je n'aime pas la façon dont ils sont convertis, tant qu'ils sont convertis de la même façon à chaque fois. - La conversion d'un
char
à ununsigned char
est une conversion. La conversion dechar *
àunsigned char*
et puis la lecture les éléments en supposant qu'ils ont été convertis lorsqu'ils n'ont pas, c'est très différent. Il fonctionne sur un système où la conversion n'est pas réellement nécessaire un changement dans la représentation (par exemple, sur l'un deux, le système du complément), mais comme c'est une mise en œuvre spécifique de l'hypothèse qu'il est approprié qu'un explicitereinterpret_cast
est nécessaire.
Vous devez vous connecter pour publier un commentaire.
Ils sont complètement différents types de standard:
De manière analogue, c'est aussi pourquoi la suivante échoue:
a
etb
sont complètement différents types, vraiment ce que vous êtes en questionnement est pourquoi static_cast de manière restrictive quand il peut effectuer les opérations suivantes sans problèmeet pourquoi ne peut-il pas en déduire que les types de cibles sont les mêmes bits largeur de champ et peut être représentée? Il peut le faire pour les types scalaires, mais pour les pointeurs, à moins que la cible est dérivée de la source et vous souhaitez effectuer un abattu alors la conversion entre les pointeurs n'est pas d'aller travailler.
Bjarne Stroustrop états pourquoi
static_cast
's sont utiles dans ce lien: http://www.stroustrup.com/bs_faq2.html#static-cast mais sous une forme abrégée, il appartient à l'utilisateur d'indiquer clairement quelles sont leurs intentions et à donner le compilateur l'occasion de vérifier que ce que vous avez l'intention peut être atteint, carstatic_cast
ne prend pas en charge la conversion entre les différents types de pointeur puis le compilateur peut intercepter cette erreur d'alerter l'utilisateur et si ils veulent vraiment faire de la conversion, ils utilisentreinterpret_cast
.unsigned char a = 255; char b = static_cast<char>(a);
?static_cast
entreunsigned char*
etchar*
, mais il est fondamentalement parce qu'ils sont de types différents, nous ne sommes pas surpris que vous pouvez statique de la fonte entre les types commefloats
àints
, et en fait, unsigned char à char, maisstatic_cast
est ce qu'il fait de l'avantage évident par rapport à c-style jette est que vous obtenez de la compilation des erreurs si vous essayez de convertir entre les différents types, comme dans votre cas, il est lié à tant de poster: stackoverflow.com/questions/2473628/...int
etdouble
ont des largeurs différentes (et qui ne sont même pas représentés de la même manière!), donc, si vous lancez àdouble *
vous pourriez accidentellement piétiner la mémoire si vous ne*d = 3.14
. Mon utilisation de "ridicule" ne s'applique qu'à la même largeur primitives.static_cast
n'est pas possible entreunsigned int*
etint*
qui est analogue à votre question, le stockage et la largeur est la même pour les deux, maisstatic_cast
détecte au moment de la compilation qu'ils sont tous les deux différents typesint
etfloat
. Ils peuvent avoir la même taille, mais si vous avez uneint
, puis essayez de le lire comme unfloat
, puis ce que vous obtenez dépend exactement commentfloat
est stockée dans la mémoire. Et depuis la spécification ne dire commentfloat
est stocké dans la mémoire, le cahier des charges pas définir ce qu'est leint
ressemble. Rappelez-vous: Le C++ standard existe pour fournir des garanties au sujet de ce que vous obtenez. Afin de définir ce comportement, le standard aurait du détail commentfloat
est mis en mémoire, ainsi que la façon dontint
est mis en mémoire.static_cast
est une chienne bien, permettant pour les inconditionnels de sortie dans l'arbre de dérivation.vous essayez de convertir sans rapport avec les pointeurs avec un static_cast. Ce n'est pas ce static_cast est pour. Vous pouvez voir ici: La Conversion De Type.
Avec static_cast vous pouvez convertir des données numériques (par exemple, char, unsigned char devrait fonctionner) ou un pointeur vers les classes connexes (liées par un héritage). C'est à la fois pas le cas. Vous voulez convertir un sans rapport avec pointeur à l'autre de sorte que vous avez à utiliser reinterpret_cast.
Fondamentalement, ce que vous essayez de faire est pour le compilateur la même chose que d'essayer de convertir un char * à un void *.
Ok, voici quelques réflexions supplémentaires pourquoi le fait de permettre ceci est fondamentalement mauvais. static_cast peut être utilisé pour convertir les types numériques les uns dans les autres. Donc, il est parfaitement légal d'écrire ce qui suit:
ce qui est possible aussi: les
Si vous regardez ce code en assembleur, vous verrez que le second cast n'est pas une simple ré-interprétation de la séquence de bits de d, mais au lieu de cela quelques instructions en assembleur pour les conversions sont insérées ici.
Maintenant, si nous prolongeons ce comportement à des tableaux, le cas où tout simplement une manière différente d'interpréter la séquence de bits est suffisante, il pourrait fonctionner. Mais ce que sur le casting des tableaux de doubles à des tableaux d'entiers?
C'est là que vous devez déclarer que vous simple voulez une ré-interprétation de modèles de bits - il y a un mécanisme appelé reinterpret_cast, ou vous devez faire un peu de travail supplémentaire. Comme vous pouvez le voir simple extension de la static_cast de pointeur /tableaux n'est pas suffisant, car il doit se comportent de manière semblable à static_casting valeurs des types. Cela a parfois besoin de plus de code, et il n'est pas clairement définissable comment cela doit être fait pour les tableaux. Dans votre cas - arrêt à \0 - parce que c'est la convention? Ce n'est pas suffisant pour les non-chaîne de cas (nombre). Ce qui va se passer si la taille des données-type de changements (par exemple, int vs double sur x86-32 bits)?
Le comportement que vous souhaitez ne peuvent pas être correctement définie pour tous les cas d'utilisation c'est pourquoi il n'est pas dans la norme C++. Sinon, vous n'avez plus à vous rappeler des choses comme: "je peux lancer ce type à l'autre tant qu'ils sont de type entier, et de même largeur,...". De cette manière, il est tout à fait clair - soit ils sont liés à des CLASSES - ensuite, vous pouvez lancer les pointeurs, ou ils sont des types, alors vous pouvez lancer les valeurs.
T1
est "liée" àT2
, puisT1 *
doit être "lié" àT2 *
. Pourquoi n'est-ce pas que de taper la règle du son (pour les types primitifs)?unsigned char a = 255; char b = static_cast<char>(a);
Il semble un peu étrange, car siT1
etT2
sont des classes, la distribution entre les pointeurs n'est pas saine, car vous pourriez faire quelque chose comme:class A;
class B : public A;
B *b = new B[4];
b[0] = B();
A *a = static_cast<A *>(b);
a[1] = A();
B b1 = b[1]; // oops
Il semble que le que moment de la fonte devrait être en sécurité est entre les types primitifs.En plus d'être des pointeurs,
unsigned char *
etchar *
n'ont rien en commun (EdChum déjà mentionné le fait quechar
,signed char
etunsigned char
sont de trois types différents). On pourrait dire la même chose pourFoo *
etBar *
types de pointeur de toute dissemblables structures.static_cast
signifie qu'un pointeur du type de source peut être utilisé comme un pointeur du type de destination, ce qui nécessite un sous-type de relation. Par conséquent, il ne peut pas être utilisé dans le contexte de votre question, ce que vous avez besoin est soitreinterpret_cast
qui fait exactement ce que vous voulez ou un style C cast.