12
votes

Pires effets secondaires de la signature des caractères. (Explication des effets de la signature sur les caractères et les fonts)

Je travaille souvent avec des bibliothèques qui utilisent des charcuter lorsque vous travaillez avec des octets en C ++. L'alternative consiste à définir un "octet" comme un caractère non signé, mais pas la norme qu'ils ont décidé d'utiliser. Je passe fréquemment des octets de C # dans les dlls C ++ et je les ai lancées pour travailler avec la bibliothèque.

Lors de la coulée intensive vers des caractères ou des caractères à d'autres types simples, quels sont certains des effets secondaires pouvant survenir. Plus précisément, lorsque ce code cassé vous avez travaillé et comment avez-vous trouvé c'était à cause de la charcuness?

Lucky Je n'ai pas rencontré cela dans mon code, j'ai utilisé un truc de casting de charret dans une classe de systèmes embarqués à l'école. Je cherche à mieux comprendre la question depuis que je pense que cela est pertinent pour le travail que je fais.


2 commentaires

Je dirais que la bonne alternative à octet est uint8_t telle qu'elle est normalisée


Édité ma réponse maintenant. Il montre un exemple (composé) qui est assez réaliste.


8 Réponses :


1
votes

Celui qui me gêne le plus:

typedef char byte;

byte b = 12;

cout << b << endl;


7 commentaires

Cela ne devrait-il pas être Typedef Char Byte ?


@roe je suis confus par Tapef presque tout le temps et je l'écris comme ce que Kornel a aussi fait: P


@roe - Ouais, une autre chose qui m'agace:>


@Arak, dans mon cas c'est parce que je suis d'un fond Pascal - type d'octet = char; fait plus de sens: p


Cela doit être Typedef non signé l'octet de caractère; !!! Le type Char est pas garanti d'être signé / non signé. C'est pourquoi GCC a des options de ligne de commande pour définir le comportement.


@Andidog, le spécificateur de la signature a été envoyé exprès :)


@Arak: Rappelez-vous simplement que TypeDef Syntax correspond aux déclarations de variable: Type réel Tout d'abord, puis le nom.



1
votes

J'ai été mordu par la charcuness en écrivant des algorithmes de recherche qui utilisaient des caractères du texte sous forme d'indices dans des arbres de l'état. J'ai également eu des problèmes lors de l'expansion des caractères en types plus importants et que le bit de signe se propage à cause des problèmes ailleurs.

J'ai découvert quand j'ai commencé à obtenir des résultats bizarres et que Segfault découlant de la recherche de textes autres que celui que j'avais utilisé lors du développement initial (évidemment des caractères avec des valeurs> 127 ou <0 vont causer cela, et gagné ' t nécessairement être présent dans vos fichiers texte typiques.

Vérifiez toujours une signature d'une variable lorsque vous travaillez avec elle. Généralement maintenant, je fais des types signés à moins d'avoir une bonne raison, sinon, jetant si nécessaire. Cela convient parfaitement à l'utilisation omniprésente de char dans les bibliothèques pour représenter simplement un octet. Gardez à l'esprit que la signature de Char n'est pas définie (contrairement à d'autres types), vous devez le donner un traitement spécial et être intéressant.


0 commentaires

4
votes

Un risque majeur est si vous devez déplacer les octets. Un caractère signé conserve le signe de signalisation lorsque je suis décalé, alors qu'un caractère non signé ne le fait pas. Voici un petit programme de test:

#include <stdio.h>

int main (void)
{
    signed char a = -1;
    unsigned char b = 255;

    printf("%d\n%d\n", a >> 1, b >> 1);

    return 0;
}


3 commentaires

Vous supposez que le complément de deux fois en plus de Char_bit est 8, mais le changement de valeur négative est défini de toute façon. (Une mise en œuvre peut le traiter de la même manière que non signée ou différente et suivre la norme de toute façon.)


Avatar: C'était une pâte de coupe droite à partir d'un fichier de code. J'ai donc utilisé l'indentation que je préfère utiliser en code. Je l'ai réparé maintenant, cependant. Roger: Vous avez raison.


Vatine, je faisais référence à ces tags. Texte indent par quatre espaces pour le transformer en bloc de code. Vous pouvez utiliser le bouton avec celles et zéros pour indenter le texte. Vous devez rarement utiliser des balises HTML sur le débordement de la pile. Et faire lisez la page que j'ai liée à.



0
votes

Lors de la coulée intensive vers des caractères ou des caractères à d'autres types simples

Le point critique est que la mise en forme d'une valeur signée d'un type primitif à un autre type (plus grand) ne conserve pas le motif de bits (en supposant le complément de deux). Un caractère signé avec motif de bits 0xff est -1, tandis qu'un court-tout signé avec la valeur décimale -1 est 0xfff . Casting d'un caractère non signé avec valeur 0xFF à un abrégé non signé, cependant, des rendements 0x00ff . Par conséquent, pensez toujours à une snovité appropriée avant de dire à un type de données plus grand ou plus petit. Ne portez jamais de données non signées dans des types de données signés si vous n'avez pas besoin de - si une bibliothèque externe vous oblige à le faire, faites la conversion aussi tard possible (ou le plus tôt possible si le code externe agit comme source de données).


0 commentaires

0
votes

Vous échouerez misérablement lors de la compilation de plusieurs plates-formes car la norme C ++ ne définit pas char d'une certaine "Signité".

GCC introduit -fsigned-char et -Funsigned-char Options pour forcer certains comportements. Plus sur ce sujet peut être trouvé ici , par exemple.

EDIT:

Comme vous avez demandé des exemples de code brisé, il existe de nombreuses possibilités de casser le code qui traite des données binaires. Par exemple, image Vous traitez des échantillons audio 8 bits (plage -128 à 127) et vous souhaitez détremper le volume. Maintenant, imaginez ce scénario (dans lequel le programmateur naïf assume char == signé caractère ): xxx

J'espère que vous aimez cet exemple ;-) Mais Pour être honnête, je n'ai jamais vraiment rencontré de tels problèmes, pas même comme un débutant autant que je puisse me rappeler ...

J'espère que cette réponse est suffisante pour vous des descentes. Qu'en est-il d'un court commentaire?


0 commentaires

0
votes

Les spécifications de langue C et C ++ définissent 3 types de données pour maintenir les caractères: char , signé Char et non signé Char . Ces derniers 2 ont été discutés dans d'autres réponses. Regardons le type char .

La ou les normes (s) disent que le type Char Type de données peut être signé être signé ou non signé et est une décision de mise en œuvre. Cela signifie que certains compilateurs ou versions de compilateurs peuvent implémenter char différemment. L'implication est que le type de données Char n'est pas propice aux opérations arithmétiques ou booléennes. Pour les opérations arithmétiques et booléennes, signé et non signé des versions de Char fonctionnera bien.

En résumé, il existe 3 versions de type de données char . Le type Char fonctionne bien pour maintenir les caractères, mais n'est pas adapté à l'arithmétique à travers les plates-formes et les traducteurs car il est la signature est la mise en œuvre définie.


0 commentaires

2
votes

Les plus évidents Gotchas viennent lorsque vous devez comparer la valeur numérique d'un char code> avec une constante hexadécimale lors de la mise en œuvre de protocoles ou de schémas de codage.

Par exemple, lors de la mise en œuvre Telnet, vous voudrez peut-être vouloir Faites cela. P>

if (ch == '\xff')               // OK

if ((unsigned char)ch == 0xff)  // OK, so long as char has 8-bits

if (ch == (char)0xff)           // Usually OK, relies on implementation defined behaviour

if ((unsigned)ch == 0xff)       // still wrong


0 commentaires

0
votes

Extension de signe. La première version de ma fonction d'encodage d'URL a produit des chaînes telles que "% FFFFFA3".


0 commentaires