Efficace non signé-à-signé fonte d'éviter la mise en œuvre définies par le comportement
Je veux définir une fonction qui prend un unsigned int
comme argument et renvoie un int
congrus modulo UINT_MAX+1 pour l'argument.
Une première tentative pourrait ressembler à ceci:
int unsigned_to_signed(unsigned n)
{
return static_cast<int>(n);
}
Mais comme toute langue, l'avocat sait, la conversion de non signé signé pour des valeurs plus grandes que INT_MAX la mise en œuvre est définie.
Je veux mettre en œuvre la présente tel que (a) il ne repose que sur le comportement mandaté par la spécification; et (b) il compile dans un no-op sur toute machine moderne et d'optimisation du compilateur.
Comme pour bizarre machines... Si il n'y a pas signé d'int congrus modulo UINT_MAX+1 pour les unsigned int, disons que je veux lancer une exception. Si il n'y a plus d'un (je ne suis pas sûr que c'est possible), disons que je veux la plus grande.
OK, deuxième tentative:
int unsigned_to_signed(unsigned n)
{
int int_n = static_cast<int>(n);
if (n == static_cast<unsigned>(int_n))
return int_n;
//else do something long and complicated
}
Je n'ai pas beaucoup de soins au sujet de l'efficacité quand je ne suis pas sur un deux-système du complément, car à mon humble avis, c'est peu probable. Et si mon code devient un goulet d'étranglement sur l'omniprésence d'un signe-amplitude systèmes de 2050, eh bien, je parie que quelqu'un peut comprendre et d'optimiser l'époque.
Maintenant, cette deuxième tentative est assez proche de ce que je veux. Bien que le casting de int
la mise en œuvre est définie pour certains intrants, les acteurs de unsigned
est garanti par la norme afin de préserver la valeur modulo UINT_MAX+1. Si la condition n'vérifier exactement ce que je veux, et compiler en rien sur tout le système je suis susceptible de rencontrer.
Cependant... je suis encore un casting pour int
sans vérifier d'abord si elle va invoquer la mise en œuvre définies par le comportement. Sur un hypothétique système en 2050, elle pourrait faire de qui-sait-quoi. Donc, disons que je veux éviter.
Question: Quelle devrait être ma "troisième tentative de" ressembler?
Pour résumer, je veux:
- Fonte de unsigned int signé int
- De préserver la valeur mod UINT_MAX+1
- Invoquer standard mandat comportement
- Compiler dans un no-op sur un deux-complément de la machine avec le compilateur optimisant
[Mise à jour]
Permettez-moi de donner un exemple pour montrer pourquoi ce n'est pas une question triviale.
Envisager un hypothétique implémentation C++ avec les propriétés suivantes:
sizeof(int)
est égal à 4sizeof(unsigned)
est égal à 4INT_MAX
est égal à 32767INT_MIN
est égal à -232 + 32768UINT_MAX
est égale à 232 - 1- Arithmétique sur
int
modulo 232 (dans la gammeINT_MIN
parINT_MAX
) std::numeric_limits<int>::is_modulo
est vrai- Casting unsigned
n
int préserve la valeur de 0 <= n <= 32767 et les rendements zéro sinon
Sur cette hypothétique mise en œuvre, il y a exactement un int
valeur congruents (mod UINT_MAX+1) pour chaque unsigned
valeur. Donc ma question serait bien définis.
Je prétends que cet hypothétique C++ mise en œuvre pleinement conforme à la C++98, C++03, et de C++11 cahier des charges. J'avoue que je n'ai pas mémorisé chaque parole de tous... Mais je crois que j'ai lu les sections pertinentes soigneusement. Donc, si vous voulez que j'accepte votre réponse, vous devez (a) citer un spec que les règles de cette hypothétique mise en œuvre ou (b) les manipuler correctement.
En effet, une réponse correcte doit gérer chaque hypothétique mise en œuvre permise par la norme. C'est ce qui "invoquer standard mandat comportement" signifie, par définition.
D'ailleurs, notez que std::numeric_limits<int>::is_modulo
est totalement inutile, ici, pour de multiples raisons. Pour une chose, il peut être true
même si non signé-à-signé jette de ne pas travailler pour de grandes valeurs non signées. Pour l'autre, il peut être true
même sur un complément ou un signe-amplitude systèmes, si l'arithmétique est simplement modulo l'ensemble de l'intervalle entier. Et ainsi de suite. Si votre réponse dépend is_modulo
, c'est mal.
[Mise à jour 2]
hvd réponse m'a appris quelque chose: Mon hypothétique implémentation C++ pour les entiers est pas permise par les techniques modernes de C. C99 et C11 normes sont très spécifiques au sujet de la représentation des entiers signés; en effet, ils ne permettent que deux en complément, ceux-compléter et signer magnitude (section 6.2.6.2 paragraphe (2); ).
Mais le C++ n'est pas C. Comme il s'avère, de ce fait, se trouve au cœur même de ma question.
Le C++98 norme a été basé sur la plus ancienne C89, qui dit (section 3.1.2.5):
Pour chaque entier signé types, il existe un correspondant (mais
différents) type entier non signé (désigné par le mot-clé
non signé), qui utilise la même quantité de stockage (y compris le signe
de l'information) et a les mêmes exigences alignement. La gamme de
non négatif valeurs d'un entier signé de type est un sous-groupe de la
correspondant de type entier non signé, et la représentation de la
même valeur dans chaque type est le même.
C89 ne dit rien sur un seul bit de signe ou permettant seulement deux-complément de/ceux-complément/signe-amplitude.
Le C++98 standard adopté cette langue presque mot à mot (section 3.9.1 paragraphe (3)):
Pour chaque entier signé types, il existe un correspondant
(mais différentes) type entier non signé: "unsigned char
", "unsigned
", "
short intunsigned int
", et "unsigned long int
", chacun de
qui occupe la même quantité de stockage et a le même alignement
exigences (3.9) que le type entier signé ; que
est, chaque entier signé de type a, l'objet même de la représentation comme
son correspondant entier non signé type. La gamme de positif
les valeurs d'un entier signé de type est un sous-groupe de correspondants
type entier non signé, et la valeur de la représentation de chaque
correspondant signed/unsigned type doit être le même.
Le C++03 standard utilise essentiellement identique de la langue, comme le fait de C++11.
Pas de C++ standard spec limite son entier signé auprès de tout C spec, autant que je puis dire. Et il n'y a rien de mandater un seul bit de signe ou quelque chose du genre. Tout ce qu'elle dit, c'est que non négatif entiers signés doivent être un sous-groupe de correspondants non signé.
Donc, encore une fois je demande que INT_MAX=32767 avec INT_MIN=-232+32768 est autorisée. Si votre réponse suppose sinon, elle est incorrecte, à moins que vous citez un C++ standard prouver que j'ai tort.
- En fait, je l'ai dit exactement ce que je veux dans ce cas: "Si il n'y a pas signé d'int congrus modulo UINT_MAX+1 pour les unsigned int, disons que je veux lancer une exception." C'est, je veux le "droit" signé int à condition qu'il existe. Si elle n'existe pas-comme cela pourrait se produire dans le cas, par exemple, de rembourrage bits ou en complément des représentations -- je veux détecter et de les traiter pour l'invocation de la fonte.
- désolé, pas sûr de savoir comment j'ai manqué.
- Btw, je pense que dans votre hypothétique délicate de la mise en œuvre
int
a besoin d'au moins 33 bits pour le représenter. Je sais que c'est seulement une note de bas de page, de sorte que vous pouvez faire valoir qu'il n'est pas normatif, mais je pense que la note de bas de page 49 en C++11 est prévu pour être vrai (puisque c'est la définition d'un terme utilisé dans le standard) et il n'est pas en contradiction avec quelque chose explicitement mentionné dans le texte normatif. Donc, toutes les valeurs négatives doivent être représentée par une séquence de bits dont le bit le plus élevé est défini, et par conséquent, vous ne pouvez pas cram2^32 - 32768
en 32 bits. Non pas que votre argument repose en aucune manière sur la taille deint
. - Et concernant vos modifications dans hvd réponse, je pense que vous avez mal interprété la note 49. Vous dites que signe-amplitude est interdit, mais il ne l'est pas. Vous avez lu comme: "les valeurs représentées par les bits suivants sont additifs, commencer par 1, et (sont multipliés par les intégrales puissance de 2, sauf peut-être pour le bit à la position la plus haute)". Je crois qu'il faut le lire, "les valeurs représentées par une succession de bits (sont additifs, commencer par 1, et sont multipliés par les intégrales de puissance de 2), sauf peut-être pour le bit à la position la plus élevée". C'est, tous les paris sont éteints si le bit est défini.
- Votre interprétation est peut-être exacte. Si oui, il n'règle mon hypothétique... Mais il introduit également un très vaste nombre de possibilités, faisant de cette question extrêmement difficile de répondre. En fait, cela ressemble à un bug dans la spec pour moi. (Apparemment, le C comité pensais et il fixe seront raffinés en C99. Je me demande pourquoi C++11 ne pas adopter leur approche?)
- Si une application utilise un " complément ou le signe-amplitude format, sont des opérateurs booléens définie comme l'exploitation des matières bits, ou sont-ils défini comme un fonctionnement dans un mode compatible avec le complément à deux de format (dans ce cas, la seule signification de la représentation devrait être (1), le comportement de ~INT_MAX, et (2), les syndicats ou d'autres techniques d'aliasing types.
- Je pense que tu veux dire "les opérateurs au niveau du bit", pas "opérateurs Booléens". (Le dernier fonctionner sur les Booléens; par exemple,
&&
ou||
.) Je crois que la réponse à votre question est que les opérateurs au niveau du bit (comme&
et|
) fonctionnent sur la "valeur de la représentation de l'entier. Si vous souhaitez assurer un comportement cohérents avec en complément à deux sur le format" vous avez besoin de jeter les arguments de leurs les formulaires non signés. - En d'autres termes, étant donné
int n;
, réellement portable calcul de "n mod 16" [par opposition à "n reste 16"] nécessite(unsigned)n & 15
plutôt que de simplementn & 15
? Je me demande combien de code utilise délibérément des opérateurs au niveau du bit sur autre chose que complément à deux valeurs? Je souhaite que le C comité des normes permettrait d'ajouter les manières de préciser qu'un programme doit utiliser notamment entier de la sémantique ou de refuser de compilation; comme il est, de la langue, il est beaucoup plus facile d'écrire du code qui semble correct, mais s'arrête sur quelques raisonnable implémentations que d'écrire du code portable.
Vous devez vous connecter pour publier un commentaire.
Expansion sur user71404 réponse:
Si
x >= INT_MIN
(garder les règles de la promotion de l'esprit,INT_MIN
est converti enunsigned
), puisx - INT_MIN <= INT_MAX
, si ce n'aurez pas de débordement.Si ce n'est pas évident, jetez un oeil à la demande "Si
x >= -4u
, puisx + 4 <= 3
.", et gardez à l'esprit queINT_MAX
sera au moins égal à la valeur mathématique de INT_MIN - 1.Sur les systèmes les plus courants, où
!(x <= INT_MAX)
impliquex >= INT_MIN
, l'optimiseur doit être en mesure (et sur mon système, en est capable) pour supprimer la deuxième case, de déterminer que les deuxreturn
déclarations peuvent être compilés dans le même code, et de supprimer la première case de trop. L'assembly généré inscription:L'hypothétique mise en œuvre dans votre question:
n'est pas possible, n'a donc pas besoin d'une attention particulière.
INT_MIN
sera égale à-INT_MAX
, ou à-INT_MAX - 1
. Cela découle de C représentation des types d'entiers (6.2.6.2), ce qui nécessiten
bits à la valeur de bits, un bit à bit de signe, et n'autorise qu'un seul piège de la représentation (non compris les représentations qui sont invalides en raison de rembourrage bits), à savoir celui qui serait autrement représentent négatif zéro /-INT_MAX - 1
. C++ ne permet pas à un nombre entier quelconque des représentations au-delà de ce que le C permet.Mise à jour: Microsoft compilateur ne semble pas remarquer que
x > 10
etx >= 11
tester la même chose. Il ne génère le code désiré six >= INT_MIN
est remplacé parx > INT_MIN - 1u
, qu'il peut détecter comme la négation dex <= INT_MAX
(sur cette plate-forme).[Mise à jour à partir interlocuteur (Nemo), de l'élaboration de notre discussion ci-dessous]
Je crois que cette réponse fonctionne dans tous les cas, mais compliqué raisons. J'ai la chance d'attribution de la prime à cette solution, mais j'ai envie de capturer tous les détails croustillants dans le cas où quelqu'un se soucie.
Nous allons commencer avec le C++11, section 18.3.3:
Ici, un Standard "C" signifie que le C99, dont les spécifications limite sérieusement la représentation des entiers signés. Ils sont comme des entiers non signés, mais avec un peu dédié à "signer" et de zéro ou plusieurs bits dédiés à "padding". Le rembourrage bits ne contribuent pas à la valeur de l'entier, et le bit de signe contribue seulement que deux en complément, ceux-complément, ou le signe-amplitude.
Depuis C++11 hérite de la
<climits>
macros de C99, INT_MIN est soit -INT_MAX ou -INT_MAX-1, et hvd code est garanti pour fonctionner. (Notez que, en raison du rembourrage, INT_MAX pourrait être beaucoup moins que UINT_MAX/2... Mais grâce à la manière signé->unsigned jette travail, cette réponse poignées fine).C++03/C++98 est plus délicat. Il utilise la même formulation pour hériter
<climits>
de "Standard C", mais maintenant Standard "C" signifie C89/C90.Tous ces -- C++98, C++03, C89/C90 -- le libellé je donne à ma question, mais également inclure ce (C++03 section 3.9.1 paragraphe 7):
Note de bas de page (44) définit la "pure numération binaire du système":
Ce qui est intéressant à propos de cette formulation est qu'il est en contradiction avec lui-même, parce que la définition de "pure numération binaire système" n'a pas permis un signe et l'ampleur de la représentation! Il ne permet pas de haut bits d'avoir, disons, la valeur -2n-1 (complément à deux) ou -(2n-1-1) (ceux complément). Mais il n'y a pas de valeur pour le peu élevé que les résultats dans le signe et l'ampleur.
De toute façon, mon "hypothétique mise en œuvre" n'est pas considéré comme "pur binaire" en vertu de cette définition, il est exclu.
Cependant, le fait que la haute bit est spécial signifie que nous pouvons l'imaginer contribuant aucune valeur: Une petite valeur positive, énorme valeur positive, de petite valeur négative, ou à une énorme valeur négative. (Si le bit de signe peut contribuer -(2n-1-1), pourquoi pas(2n-1-2)? etc.)
Donc, imaginons un entier signé de représentation qui affecte une wacky valeur le "signe" peu.
Une petite valeur positive pour le bit de signe entraînerait une plage positive
int
(éventuellement aussi grand queunsigned
), et hvd du code gère cela très bien.Une énorme valeur positive pour le bit de signe entraînerait
int
avoir un maximum de plus deunsigned
, ce qui est interdit.Une énorme valeur négative pour le bit de signe entraînerait
int
représentant un non-contiguë à une gamme de valeurs, et d'autres libellé dans la spécification des règles de sortir.Enfin, que diriez-vous d'un bit de signe qui contribue à une petite quantité négative? Pourrions-nous avoir un 1 dans le "bit de signe" contribuer, disons, de -37 à la valeur de l'int? Alors INT_MAX serait (dire) 231-1 et INT_MIN serait -37?
Cela entraînerait un certains nombres d'avoir deux représentations... Mais ceux-compléter donne deux représentations à zéro, et qui est autorisé conformément à la "Exemple". Nulle part dans la spec dire que c'est le zéro seulement entier qui peut avoir deux représentations. Je pense donc que cette nouvelle hypothétique est autorisé par les spécifications.
En effet, une valeur négative de -1 en bas à
-INT_MAX-1
semble être admissible en tant que valeur pour le "bit de signe", mais rien de plus petite taille (de peur que la fourchette de non-contigus). En d'autres termes,INT_MIN
peut-être quelque chose de-INT_MAX-1
à -1.Maintenant, devinez quoi? Pour la deuxième distribution dans hvd du code pour éviter de mise en œuvre définies par le comportement, nous avons juste besoin
x - (unsigned)INT_MIN
inférieure ou égale àINT_MAX
. Nous avons seulement montréINT_MIN
est au moins-INT_MAX-1
. Évidemment,x
est au plusUINT_MAX
. Le moulage d'un nombre négatif non signé est le même que l'ajout deUINT_MAX+1
. Mettre tout cela ensemble:si et seulement si
Ce dernier est ce que nous a juste montré, de sorte que même dans cette perverse cas, le code fonctionne réellement.
Qui épuise toutes les possibilités, mettant ainsi un terme à cette extrêmement exercice académique.
Bas de ligne: Il y a quelques gravement sous-comportement spécifié pour les entiers signés en C89/C90 qui a hérité du C++98/C++03. Il est fixé en C99, et de C++11 indirectement hérite de la résoudre en intégrant
<limits.h>
de C99. Mais même en C++11 conserve l'auto-contradictoire "pure représentation binaire" les mots...<limits.h>
sont définis dans la norme C++ comme ayant la même signification que dans la norme, de sorte que tous C en matière deINT_MIN
etINT_MAX
sont hérités en C++. Vous avez raison que C++03 désigne C90, et C90 est imprécis sur les permis entier des représentations, mais le C99 changement (hérité au moins via<limits.h>
par le C++11, je l'espère aussi de façon plus simple) de la limiter à ces trois était l'un que codifié existant pratique: pas d'autres implémentations de l'existence.INT_MIN
etc. sont héritées de C. Mais cela ne signifie pas que le valeurs sont. (En effet, comment pourraient-ils, car chaque réalisation est différente?) Votre inférence queINT_MIN
est à moins de 1 de-INT_MAX
dépend de la formulation qui ne semble tout simplement pas en C++ spec. Ainsi, tandis que le C++ n'héritent de la signification sémantique des macros, des spec ne pas fournir (ou d'en hériter) de la formulation qui prend en charge votre inférence. Cela semble être une erreur dans le C++ spec qui empêche de pleinement conforme efficace non signé-à-signé en fonte.INT_MIN
n'est pas nécessaire pour être le minimum représentable valeur de typeint
, parce que pour ce que C est en cause, si le type ne correspond pas aux exigences deint
, le C standard ne peut pas couvrir que la mise en œuvre de quelque manière que ce soit, et le C++ standard ne fournit pas de définition autre que "ce que le C standard dit". Je vais vérifier si il y a une explication.<climits>
a le même contenu, comme "la Norme d'en-tête C<limits.h>
", il s'ensuit queINT_MIN
etc. doit être valide pour C. Donc, qui prend soin de C++11 (mais pas du C++03, pour qui "Standard C" signifiait C90). Je vais probablement le vent jusqu'à accepter cette réponse.INT_MAX
est nécessairement dans un délai de 1 deINT_MIN
par le C spec.int
avoir valeur de 31 bits, 1 bit de signe, et 32 bits de padding, tandis queunsigned
a 64 de la valeur des bits. Je crois qu'il permet égalementint
avoir valeur de 31 bits, 1 bit de signe, pas de rembourrage bits, tandis queunsigned
a valeur de 31 bits et un peu de rembourrage. J'ai pris ces implémentations en compte lors de venir avec ma réponse. Pour leur mise en œuvre,INT_MIN
sera toujours soit-INT_MAX
ou-INT_MAX - 1
;INT_MAX
juste ne pas être égale àUINT_MAX / 2
.unsigned
est égal au paramètre, et si non, force brutale, c', la vérification de chaque valeur possible deINT_MIN
tout le chemin àINT_MAX
. Mais c'est évidemment une très mauvaise solution. 🙂static_cast<int>(x - INT_MIN)
. Il est évalué seulement si x >= INT_MIN, après la promotion de INT_MIN non signé. Avec l'OP INT_MIN = -2^n + 32768, la promotion des rendements 32768, donc, mettons x lors d'une série 1 m + 32768. En soustrayant INT_MIN qui est semblable à 32768, puis donne un tour de 1 million de dollars. Qui est à l'extérieur de l'OP de l'exempleint
de gamme, donc le casting appelle impl. def. comportement... 🙁Ce code s'appuie uniquement sur le comportement, mandaté par la spécification, de sorte que la condition (a) est facilement satisfaite:
Il n'est pas si facile avec la condition (b). Cette compile dans un no-op avec gcc 4.6.3 (-Os, -O2-O3) et avec clang 3.0 (-Os, -O, -O2-O3). Intel 12.1.0 refuse d'optimiser cette. Et je n'ai aucune info à propos de Visual C.
result
débordements; débordement d'entier n'est pas défini; par conséquent, la boucle s'arrête; c'est pourquoii == n
à la cessation d'emploi; par conséquentresult
est égal àn
. J'ai toujours préférer hvd de réponse (pour les non-pathologiques du comportement de la moins-smart compilateurs), mais cela mérite plus de votes.n
est certaine valeur non signée eti
doit finalement atteindre chaque valeur non signée.Vous pouvez indiquer explicitement au compilateur ce que vous voulez faire:
Compile avec
gcc 4.7.2
pourx86_64-linux
(g++ -O -S test.cpp
) àUINT_MAX
est une expression de typeunsigned int
, et qui rend l'ensemble de votrestatic_cast<int>(n + INT_MIN) - (UINT_MAX + INT_MIN + 1)
de ce type. Il devrait être possible de corriger cela, et je m'attends à encore être compilé le même.Si
x
est notre entrée...Si
x > INT_MAX
, nous voulons trouver une constantek
tels que0
<x - k*INT_MAX
<INT_MAX
.C'est facile --
unsigned int k = x /INT_MAX;
. Alors, laissezunsigned int x2 = x - k*INT_MAX;
Nous pouvons maintenant lancer
x2
àint
en toute sécurité. Laissezint x3 = static_cast<int>(x2);
Maintenant, nous voulons soustraire quelque chose comme
UINT_MAX - k * INT_MAX + 1
dex3
, sik > 0
.Maintenant, sur un 2s, le système du complément, tant que
x > INT_MAX
, cela fonctionne à:Noter que
UINT_MAX+1
est zéro en C++ de la garantie, la conversion en int a été un noop, et nous avons soustraitk*INT_MAX
ensuite ajouté sur le dos "de la même valeur". Donc acceptable optimiseur doit être en mesure d'effacer tout ce qui tomfoolery!Qui laisse le problème de
x > INT_MAX
ou pas. Eh bien, nous créons 2 branches, l'une avecx > INT_MAX
, et l'autre sans. L'un sans ne un détroit exprimés, ce qui le compilateur optimise pour un noop. L'un avec ... un noop après l'optimiseur est fait. Le smart optimiseur se rend compte que les deux branches de la même chose, et les gouttes de la branche.Des questions: si
UINT_MAX
est vraiment grand par rapport àINT_MAX
, le ci-dessus peut ne pas fonctionner. Je suis en supposant quek*INT_MAX <= UINT_MAX+1
implicitement.Nous pourrions probablement l'attaque avec un peu d'énumérations comme:
qui travaillent à 2 et 1 à 2s, le système du complément, je crois (sommes-nous garanties pour que les mathématiques au travail? C'est difficile...), et de faire de la logique sur la base de ces facilement optimiser loin sur la non-2s compléter des systèmes de...
Ceci ouvre également les cas d'exception. Il est seulement possible si UINT_MAX est beaucoup plus grande que (INT_MIN-INT_MAX), de sorte que vous pouvez mettre votre code d'exception dans un bloc if poser exactement la question, en quelque sorte, et il ne vous ralentira pas sur un système traditionnel.
Je ne suis pas exactement sûr de la façon de construire ces constantes de compilation de traiter correctement avec cette.
UINT_MAX
ne peut pas être petite par rapport àINT_MAX
, parce que la spécification garantit que chaque positive signé int est représentable comme un unsigned int. MaisUINT_MAX+1
est de zéro pour chaque système; unsigned l'arithmétique est toujours moduloUINT_MAX+1
. Encore il pourrait y avoir un noyau d'une approche pratique ici...UINT_MAX+1
est de zéro pour chaque système de " établis dans la '03-spec? Si oui, est-il une sous-section I devrait être à la recherche de sous? Merci.Mon argent est sur l'utilisation de memcpy. Tout bon compilateur sait optimiser loin:
Pour moi (Xcode 8.3.2, Apple LLVM 8.1, -O3), qui produit:
std::numeric_limits<int>::is_modulo
est une compilation constante de temps. de sorte que vous pouvez l'utiliser pour le modèle de la spécialisation. problème résolu, au moins si compilateur joue avec inline.MODIFIER: correction du code pour éviter les pièges potentiels sur la non-modulaire-int machines (une seule est connue, à savoir la archaically configuré versions de la Unisys Clearpath). Pour plus de simplicité il suffit de ne pas soutenir la valeur -2n-1, où n est le nombre de
int
valeur des bits, sur la machine (c'est à dire, sur la Clearpath). dans la pratique, cette valeur ne sera pas pris en charge par la machine, soit (c'est à dire, avec le signe et l'ampleur ou l'1 complément représentation).Je pense que le type int est au moins deux octets, de sorte que le INT_MIN et INT_MAX peut changer dans différentes plates-formes.
Types fondamentaux
≤climits≥ - tête
Ce qui est parfaitement conforme à la norme, et de compiler pour non-op sur MSVC/gcc.
Pour le code appelant comme:
Nous aurons cette assemblée de sortie (g++ -O3-S):
Et de la déclaration de
unsigned_to_signed()
commeinline
rendements:Qui est assez propre code.
cast.Out
est pas défini lorsque les bits decast.In
ne représentent pas une valeur de typeint
. Il fonctionnera dans la pratique, sur presque tous les systèmes, mais ce sera un simplestatic_cast
àint
.INT_MIN < -INT_MAX
et pas de rembourrage bits, vous avez raison. Et ce sera en effet le système le plus commun. J'ai lu la question comme nécessitant un comportement défini pour les rares systèmes de trop, mais si standard comportement défini est nécessaire pour les systèmes communs, votre réponse me semble bon.uncommon
systèmes. Cependant, cela ressemble à un comportement non défini dans la présente affaire.This is perfectly standard-compliant
: Non, la norme ne dites pas que vous obtiendrez le droit de répondre à cette voie.