2
votes

caractères non signés et sprintf () C

J'ai ce code:

int main(){

char buffer[1024];
char port = 1;
int length = 255;
char * record = "$TAG ,0 ,89 ,0, 1\n";

if(length < 0 || length > 255){
    printf("Error - length out of range for an unsigned char.\n");
    exit(1);
}

snprintf(buffer, 1024, "%c%c%s", port, (unsigned char) length, record);

int port_rc     = buffer[0];
int length_rc   = buffer[1]; 

printf("port_rc: %d\n",port_rc);
printf("length_rc: %d\n",length_rc);

return 0;

}

Sortie lorsque je l'exécute:

port_rc: 1 length_rc: -1

Je pense qu'il me manque quelque chose ici en termes de snprintf () car je ne vois pas la valeur 255 lors de la lecture du tableau qu'il a créé. Je suppose que snprintf () promeut la variable «length» en un int ou quelque chose. Quelqu'un sait-il comment je peux y parvenir?

Merci.


5 commentaires

Le premier caractère de "255" est '2' qui a la valeur 50 en ascii.


@tkausl Qu'est-ce qui vous empêche de répondre?


Allez-vous jamais obtenir 255 en utilisant un autre spécificateur de format? Le char est présumé signé, puisque vous utilisez un cast de (unsigned char) plutôt que (char) . Vous obtiendrez donc -1 .


buffer [1] a le type char , il est littéralement impossible pour lui de stocker 255 (en supposant que votre système a un caractère simple comme signé)


@ M.M - oui c'est pourquoi j'essayais d'utiliser un caractère non signé. J'ai compris et vous pouvez voir ma solution dans ma réponse.


3 Réponses :


3
votes

Je ne pense pas que vous puissiez utiliser sprintf () pour stocker 255 dans le tampon. L'argument buffer de sprintf () est un tableau de char . Le fait que char soit signé ou unsigned par défaut est défini par l'implémentation; voir Le caractère est-il signé ou non signé par défaut? . Si 255 est supérieur à CHAR_MAX , essayer de stocker 255 entraîne un comportement non défini; si l'implémentation par défaut est signé alors CHAR_MAX sera probablement 127 .

Je suggère de ne pas utiliser sprintf () code > pour stocker des nombres dans le tampon. Déclarez-le comme:

buffer[0] = port;
buffer[1] = length;
snprintf((char *)(buffer + 2), sizeof buffer - 2, "%s", record);

Ensuite, vous pouvez faire:

unsigned char buffer[127];


6 commentaires

Bien, mais cela ne renvoie pas 255 dans la variable 'length_rc'. Veuillez consulter le code modifié ci-dessus. Et si je change la «longueur» en 127 (le plus grand nombre de caractères signés), la sortie est produite comme prévu.


Je vois le problème. Le tampon est char [] , pas unsigned char [] . Donc buffer [1] est signé. Le stockage de 255 dans la mémoire tampon entraîne un comportement indéfini.


J'ai mis à jour la réponse pour montrer comment vous pouvez le faire de manière plus sûre.


Merci beaucoup @Bamar - j'ai intégré votre solution. Mon message est mis à jour pour refléter les changements de travail.


Vous devez mettre la solution de travail dans une réponse, pas dans la question.


Terminé. Merci encore.



0
votes

SOLUTION DE TRAVAIL:

int main(){

unsigned char buffer[1024];
char port = 1;
int length = 255;
char * record = "$TAG ,0 ,89 ,0, 1\n";

if(length < 0 || length > 255){
    printf("Error - length out of range for an unsigned char.\n");
    exit(1);
}

buffer[0] = port;
buffer[1] = length;
snprintf((char *)(buffer), sizeof buffer - 2, "%c%c%s", port,length,record);

int port_rc     = buffer[0];
int length_rc   = buffer[1]; 
char char_first = buffer[2];

printf("port_rc: %d\n",port_rc);
printf("length_rc: %d\n",length_rc);
printf("char_first: %c\n",char_first);


return 0;

}

RETOURS:

port_rc: 1 longueur_rc: 255 char_first: $


0 commentaires

1
votes

"Soyez prudent, cependant," lorsque vous jugez une telle "solution".

À mon humble avis, le problème fondamental - dans votre message d'origine - est que les variables port_rc et length_rc auraient dû être déclarées comme non signées entiers. Vous ne voulez pas qu'une valeur telle que $ FF soit à tort "sign-extended" pour devenir $ FFFFFFFF == -1 ...

Votre "solution" est assez différente de l'original car, comme vous le voyez, elle stocke désormais à la fois le buffer [0] et le buffer [1] avant de récupérer et d'examiner ces valeurs!


1 commentaires

Je suis d'accord mais je m'assure que le retour valide est compris entre 0 et 255 pour être sûr.