-2
votes

J'ai appris que dans le type de caractère de langage C varie de -128 à 127, mais cela ne semble pas comme ça

Cela pourrait être un problème très fondamental, mais je ne pouvais pas réussir à. Voici ce que je travaille avec.

size of char: 1
c1: ffffff80, c2: ffffff80
true or false: 1


11 commentaires

Qu'est-ce que TwoS complément d'un entier de 4 octets de -128?


Je pense que vous voyez Promotion et extension de signalisation.


Je suis confondu par votre déclaration. Dans ce code, vous avez attribué 128 à un type de caractère signé, et il a fait trop de débordement. Cela correspond à votre attente que la gamme est de -128 à 127.


1) Char Fournissez un minimum ou -128..127 ou un minimum de 0..255. Ils peuvent fournir beaucoup plus. (Il y a un système avec des caractères 32 bits.)


2) % x nécessite un non signé INT . Votre Char est en cours de promotion.


Vous dites déjà dans votre titre que la plage est -128 à 127 alors pourquoi essayez-vous d'utiliser (+) 128 ?


@ikegami Je crois que la plage minimale de Char si signée est -127..127 selon la norme.


@Christian gibbons, oh oui, bien sûr, pour accueillir les systèmes de complément de 1


Utilisez simplement le format d'impression correct % hhx 128 ne correspond pas au char et il s'agit d'un débordement entier qui est un UB.


@ikegami ou signe et magnitude.


Agongji, avec C2 = -128; , qu'avez-vous espéré? Si le code est allé, quelle valeur vous attendiez-vous au C2 ?


4 Réponses :


2
votes

Le type Char peut se comporter comme type signé Char ou comme type non signé Char Selon une option de compilateur ou par défaut de la compilateur.

Dans votre cas, le type Char se comporte comme type signé Char . Dans ce cas, char_min est égal à -128 et char_max est égal à 127 .

Donc, un objet du type Char ne peut pas contenir le nombre positif 128. Cette valeur a la représentation hexadécimale suivante 0x80 . So stocké dans un objet du type Char Il est interprété comme une valeur négative car le bit de signalisation est défini. Cette valeur négative est -128 .

donc après ces instructions xxx

Les deux objets ont la même valeur égale à < Code> -128 .

et la sortie xxx

de cet appel xxx < p> montre que les deux objets c1 et c2 sont favorisés au type int ont la même représentation d'une valeur négative. < P> Faites attention à ce que c'est un comportement défini par la mise en œuvre d'attribuer un objet du type signé avec une valeur positive qui ne peut pas être représentée dans l'objet.


2 commentaires

@Holyblackcat levant un signal signifie que le comportement est indéfini. Par exemple, vous pouvez obtenir une valeur de piège.


Merci beaucoup! Votre explication est très simple et a du sens totalement. Je suppose que je comprends. Type de caractère est 8 bits et peut contenir 128, c'est-à-dire pourquoi l'erreur de débordement ne se produit pas et 128 est simplement convertie en -128 en fonction de la définition de la mise en œuvre.



0
votes

Ici c'est expliqué: https://fr.wikipedia.org/wiki/signed_number_representations

Si -128 et 128 et tous les nombres entre les deux étaient représentés avec un octet, nous aurions 257 numéros dans cet ensemble. Cependant, nous ne sommes pas, c'est juste 256.

Son mappé comme suit décimal: [0..127, -128 ..- 1] => [0b00000000..0b11111111]. Notez que le premier bit devient 1 à -128, heureux accident;).

Aussi votre formatage de chaîne est incorrect, votre compilateur devrait vous avertir,% X attend 4 octets! Si vous prenez en compte ce que j'ai dit plus tôt, vous voyez que 0x80 est en effet 0B10000000.


0 commentaires

5
votes

dans C1 = 128; , 128 ne correspond pas au huit bits signé char que votre implémentation C utilise votre mise en œuvre. 128 est converti en Char par C 2018 6.5.16.1 2: "La valeur de l'opérande droit est convertie au type d'expression d'affectation ..."

La conversion est définie par la mise en œuvre, par 6.3.1.3 3: "Sinon, le nouveau type est signé et la valeur ne peut être représentée; Soit le résultat est défini par la mise en oeuvre ou un signal défini par la mise en œuvre est soulevé. " Votre implémentation C convertie 128, qui est 10000000 2 comme chiffre binaire non signé, à -128, qui est représentée avec les mêmes bits lors de l'utilisation de deux binaires signés. Ainsi, le résultat est que C1 contient la valeur -128.

in printf ("C1:% x, c2:% x \ n", C1, C2); , C1 est converti en un int < / code>. En effet, les règles pour appeler des fonctions avec ... doivent appliquer les promotions d'argument par défaut aux arguments correspondants, conformément aux arguments 6.5.2.2 7: "Les promotions d'argument par défaut sont effectuées sur des arguments de fin."

Les promotions d'argument par défaut incluent les promotions entière, conformément au 6.5.2.2 6. Lorsque la plage de Char est plus étroite que int , telle qu'elle est dans la plupart des implémentations, Les Promotions entier convertissent un char à un int , par 6.3.1.1 2: "Si un int peut représenter toutes les valeurs du type d'origine ... , la valeur est convertie en un int ... "

Ainsi, dans printf ("C1:% x, C2:% x \ n", C1, C2); , un int de -128 est passé comme deuxième argument. Votre implémentation C utilise le complément de deux 32 bits pour int , dans lequel -128 est représenté avec les bits 111111111111111111111110000000, que nous pouvons exprimer à Hexadecimal comme Ffffff80.

La chaîne de format spécifie une conversion à l'aide de % x . Le type d'argument approprié pour % x est non signé INT . Toutefois, votre implémentation C a accepté le int et réinterprété ses bits en tant que non signé INT . Ainsi, les bits 11111111111111111111111000000000 sont convertis en chaîne "FFFFFF80".

Ceci explique pourquoi "FFFFFF80" est imprimé. Ce n'est pas parce que C1 a quatre octets mais car il a été converti en un type à quatre octets avant d'être transmis à printf . En outre, la conversion d'une valeur négative sur ce type de quatre octets a entraîné quatre octets avec de nombreux bits.

concernant c1 == C2 évaluant à true (1), il s'agit simplement du fait que C1 a été donné la valeur -128 comme expliqué ci-dessus et c2 = = -128; attribue également la valeur -128 à c2 , donc C1 et c2 avoir la même valeur.


3 commentaires

Votre explication m'a beaucoup aidé à effacer le brouillard dans mon cerveau. Maintenant, j'ai appris la conversion intégrale, la promotion et la manière d'utiliser% Identifiant X. J'ai besoin d'apprendre à lire la définition de mise en œuvre. fonctionnalité de langue. Les programmeurs recherchent-ils généralement la page Web comme ( dii.uchile.cl/~ Daecino / fichiers / iso_c_1999_definition.pdf ) Chaque fois qu'ils ont besoin de confirmer la fonction de langue? Quoi qu'il en soit, merci beaucoup pour votre aide.


@AGONGJI Cette copie est probablement, strictement parlée, une violation du droit d'auteur. Disponible publiquement et généralement suffisantes sont les brouillons, répertoriés à EN.CPPREFERGENCE.COM/W/C/LINKS . Mais oui, bon nombre des affiches ici (probablement ceux qui gagnent un revenu en tant que développeurs possèdent une copie de la norme ISO, je suppose, avec d'autres livres de texte. La plupart des questions de langage C Technical C ont été correctement répondues. Les erreurs techniques ont tendance à être corrigées rapidement et de manière fiable ici. Mais certes, il est parfois difficile de rechercher ("Promotions d'argument par défaut" !?).


@AGONGJI: Les bons praticiens apprennent les règles assez bien qu'ils n'ont pas besoin de rechercher souvent les règles et / ou de développer des habitudes de rédaction de code qui évitent de devoir rechercher les règles et recherchent les règles si nécessaire. Après un certain temps, on se familiarise avec divers documents afin que de trouver des choses en eux deviennent plus rapides.



1
votes

dans la déclaration xxx

% x attend un argument de type non signé INT , de sorte que les valeurs de c1 < / code> et C2 est en cours de promotion de char à non signé INT , avec le bit leader étendu. Pour imprimer la valeur numérique d'un non signé char comme hex, vous devez utiliser le modificateur HH dans la conversion: xxx

comme pour les valeurs pouvant être représentées dans un char , c'est un peu plus compliqué que cela.

Les codages pour les membres de l'ensemble de caractères 1 sont garantis pour être non négatifs. Les codages pour des caractères supplémentaires peuvent être négatifs ou non négatifs.

Ainsi, en fonction de la mise en œuvre, une branche char peut représenter des valeurs dans au moins la plage [- 128..127] (supposant que le complément de deux Représentation) ou [0..255] . Je dis "au moins" depuis char_bit peut être supérieur à 8 (il existe des systèmes historiques qui ont utilisé des octets de 9 bits et des mots 36 bits). Un signé Char représentera des valeurs dans au moins la plage [- 128..127] (à nouveau, en supposant le complément de deux).

supposant Char est signé et 8 bits, puis attribuant 128 à C1 conduit à SIGNED INTEGER Overflow et le comportement sur celui-ci est indéfini , ce qui signifie que le compilateur et l'environnement d'exécution ne sont pas obligés de le gérer de manière particulière. tout résultat est "correct" en ce qui concerne la définition de la langue, que ce soit le résultat que vous attendiez ou non.


  1. Alphabet latine supérieur et minuscule, chiffres décimaux, 29 caractères graphiques, espaces blancs et caractères de commande (alimentation en ligne, flux de formulaire, onglet, etc.).


1 commentaires

Il n'y a pas de promotion à non signé INT ici. c1 , c2 subir des promotions d'argument par défaut et finir par (dans ce cas) étant int s, et comme ils n'ont pas de valeur positive, Ensuite, le comportement n'est pas défini lorsqu'il est utilisé avec des macros STDARG en tant qu'Ot non signé.