0
votes

Trouver une valeur Y telle (x -y) sera faux, quand x est un entier signé et x = 1?

La question demande,

Soit INT x = 1, trouver une valeur pour INT y où l'instruction suivante reviendra fausse: (x -y)

Je sais que la réponse devrait être de 4 octets long (8 chiffres hexagonaux), mais je ne sais pas comment aborder la question.

c

3 commentaires

Pensez à la représentation signée d'un Int par rapport à une valeur hexagonale non signée ...


Éventuellement faux lorsque y = int_min comme -int_min est UB, alors quelque chose peut arriver: c'est vrai, son faux, son un muffin à conversation . 😊


Honnêtement, je devinerais que INT_MIN est en effet la réponse destinée "correcte" à cette question, et celui qui l'a écrit, il n'est probablement pas trop familier avec le concept de UB. Donc, la question elle-même est défectueuse car elle semble supposer une représentation spécifique pour les valeurs négatives et un comportement défini spécifique pour débordement signé.


4 Réponses :


8
votes

Il n'y a aucune valeur pour y pour lequel l'expression est fausse. Si nous compilons ceci: xxx

gcc et clang avec optimisation activé générera ce code: xxx

toute autre réponse qui pense être intelligente Très probablement utilise le débordement et est un comportement non défini ou mal comprendre certains fondamentaux C.

En réalité, il n'y a pas de valeurs pour x ou y pour lequel l'expression est faux: xxx

donne la même chose: xxx


Il semble que certaines personnes manquent l'implication et la signification de Le fait que les compilateurs transforment l'expression en retour 1 . C'est la preuve que le compilateur a définitivement prouvé qu'il n'y a pas d'entrée valide pour laquelle l'expression est fausse. Sinon, il n'aurait pas été autorisé à faire cette optimisation.


2 commentaires

@mcleod_ideafix: 0x80000000 causerait un Overflow signé , qui donne lieu à comportement non défini .


La question suivante peut aider à expliquer pourquoi débordement signé provoque un comportement indéfini: Pourquoi est un comportement défini entier non signé, mais signé le débordement entier n'est pas? < / a>



-2
votes

Si int est défini comme une valeur de deux bits à deux complément, alors la valeur 0x80000000 échouera la comparaison. La raison en est que les valeurs de deux compléments ont une valeur de plus du côté négatif que du côté positif. Toute valeur positive peut être convertie en négative, mais toutes les valeurs négatives peuvent être converties en positif.

Donc, pour la valeur susmentionnée, y et -y est en réalité la même valeur et la première comparaison (x donnera "faux" où (- x> -y) donnera "vrai", rendant l'expression entière "FALSE".

Mais cela ne se produirait pas si, comme dans la réponse à @bolov, le compilateur optimise la fonction.


3 commentaires

"Ensuite, la valeur 0x80000000 échouera la comparaison" - je suis en désaccord avec cette déclaration. Il est indéfini de ce qui se passera dans ce cas. La comparaison peut être évaluée au vrai ou au faux ou le compilateur peut traiter n'importe quel code qui conduit au débordement signé comme inaccessible, ce qui lui permet d'être optimisé. C'est la nature de comportement non défini . Voir Cette excellente réponse par Microsoft Blogger Raymond Chen Pour plus d'informations sur ce que le compilateur peut faire en cas de comportement non défini.


Oui avec 0x80000000 Nous avons un comportement non défini. Cette réponse est incorrecte.


Et la réponse de Bolov a déjà prédit cette mauvaise réponse: "Toute autre réponse qui pense être intelligente utilise probablement le débordement et est en réalité un comportement non défini ou mal comprendre certains fondamentaux de C."



0
votes

trouver une valeur Y telle (x -y) sera false, lorsque X est un entier signé et x = 1?

Lorsque non signé y = 0 . xxx

sortie xxx


Oups n'a pas vu le "Trouver une valeur pour INT Y (EN HEX)" JUSQU'À PLUS.

PLATED COMMED LE TITRE question, mais est interdite dans les détails.


0 commentaires

-1
votes

La réponse est int_min == -int_min code>, je pense que vous avez déjà su comment cela fonctionne.

Mais si vous voulez faire une expérience et se sent mauvais pour l'optimisation du compilateur, Vous pouvez utiliser l'attribut noclone code> pour empêcher que le compilateur soit une proception constante, et noinline code> attribut let moins () code> est une boîte noire pour Main () code> p>

#include <limits.h>

__attribute__ ((noclone, noinline))
int less (int x, int y) {
  return x > y;
}

__attribute__ ((noclone, noinline))
int neg (int x) {
  return -x;
}

int main(void) {
  int x = 1, y = INT_MIN;
  return  less(x, y) == less(neg(y), neg(x));
}


5 commentaires

Cette réponse ne peut être valide que pour une version spécifique d'un compilateur spécifique ciblant une plate-forme spécifique et à l'aide d'un ensemble d'options spécifique. Changez toute de ces variables et cela pourrait ne plus travailler.


En général, cette réponse est fausse pour toutes les raisons notées plusieurs fois déjà. Donné y = int_min , l'utilisation de -y peut causer un débordement signé et donc un comportement non défini. Il n'y a aucun moyen de faire face à la main.


Merci@andrew Henle. J'ajoute neg () pour créer une boîte noire pour le compilateur pour résoudre l'erreur.


Votre ajout de neg () ne résout rien. Vous avez toujours retour -x . Si vous passez votre neg () fonction int_min , il essaiera de retourner -int_min . Ce qui est un comportement indéfini - à nouveau . Il n'y a pas une telle chose qu'une "boîte noire" dans des logiciels qui puisse faire de manière magique le comportement non défini disparaître - le code fait ce que le code fait si vous vous souciez de regarder à l'intérieur de la boîte ou non .. Et dans ce cas, c'est un comportement indéfini, peu importe la façon dont beaucoup de fonctions


Si le compilateur ne fait pas état de CPROP, le compilateur n'a pas pu savoir que le programme exécuterait -int_min