web-dev-qa-db-fra.com

C - conversion de tableau entier non signé en tableau de caractères non signé

J'ai un numéro int non signé (2 octets) et je veux le convertir en type char non signé. De ma recherche, je trouve que la plupart des gens recommandent de faire ce qui suit:

 unsigned int x;
 ...
 unsigned char ch = (unsigned char)x;

Est-ce la bonne approche? Je demande parce que le caractère non signé fait 1 octet et nous avons converti les données de 2 octets en 1 octet.

Pour éviter toute perte de données, je souhaite créer un tableau de caractères non signés [] et enregistrer les octets individuels dans le tableau. Je suis bloqué sur ce qui suit:

 unsigned char ch[2];
 unsigned int num = 272;

 for(i=0; i<2; i++){
      // how should the individual bytes from num be saved in ch[0] and ch[1] ??
 }

Aussi, comment pourrions-nous reconvertir le caractère non signé [2] en entier non signé.

Merci beaucoup.

16
Jake

Vous pouvez utiliser memcpy dans ce cas:

memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */

De plus, comment serait converti le caractère non signé [2] en entier non signé.

De la même manière, inversez simplement les arguments de memcpy.

19
jpalecek

Que diriez-vous:

ch[0] = num & 0xFF;
ch[1] = (num >> 8) & 0xFF;

L'opération inverse est laissée en exercice.

17
cnicutar

Et si vous utilisiez un syndicat?

union {
    unsigned int num;
    unsigned char ch[2];
}  theValue;

theValue.num = 272;
printf("The two bytes: %d and %d\n", theValue.ch[0], theValue.ch[1]);
7
abelenky

Cela dépend vraiment de votre objectif: pourquoi voulez-vous le convertir en un unsigned char? Selon la réponse à cette question, il existe plusieurs façons de procéder:

  • Tronquer: C'est ce qui a été recommandé. Si vous essayez simplement de compresser des données dans une fonction qui nécessite un unsigned char, Transtypez simplement uchar ch = (uchar)x (mais, bien sûr, méfiez-vous de ce qui se passe si votre int est trop grand).

  • Endian spécifique: Utilisez ceci lorsque votre destination nécessite un format spécifique. Habituellement, le code réseau aime tout ce qui est converti en grands tableaux endiens de caractères:

    int n = sizeof x;
    for(int y=0; n-->0; y++)
        ch[y] = (x>>(n*8))&0xff;
    

    will fait ça.

  • machine endian. Utilisez cette option lorsqu'il n'y a aucune exigence d'endianité et que les données ne se produiront que sur une seule machine. L'ordre du tableau changera selon les différentes architectures. Les gens s'en occupent généralement avec unions:

    union {int x; char ch[sizeof (int)];} u;
    u.x = 0xf00
    //use u.ch 
    

    avec memcpy:

    uchar ch[sizeof(int)];
    memcpy(&ch, &x, sizeof x);
    

    ou avec le casting simple toujours dangereux (qui est un comportement indéfini et se bloque sur de nombreux systèmes):

    char *ch = (unsigned char *)&x;
    
6
Dave

Bien sûr, un tableau de caractères suffisamment grand pour contenir une valeur plus élevée doit être exactement aussi grand que cette valeur elle-même. Vous pouvez donc simplement prétendre que cette plus grande valeur est déjà un tableau de caractères:

unsigned int x = 12345678;//well, it should be just 1234.
unsigned char* pChars;

pChars = (unsigned char*) &x;

pChars[0];//one byte is here
pChars[1];//another byte here

(Une fois que vous comprenez ce qui se passe, cela peut être fait sans aucune variable, tout simplement le casting)

4
Agent_L

Il vous suffit d'extraire ces octets à l'aide de bitwise & operator. OxFF est un masque hexadécimal pour extraire un octet. Veuillez regarder les différentes opérations sur les bits ici - http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/

Un exemple de programme est le suivant:

#include <stdio.h>

int main()
{
    unsigned int i = 0x1122;
    unsigned char c[2];

    c[0] = i & 0xFF;
    c[1] = (i>>8) & 0xFF;

    printf("c[0] = %x \n", c[0]);
    printf("c[1] = %x \n", c[1]);
    printf("i    = %x \n", i);

    return 0;
}

Production:

$ gcc 1.c 
$ ./a.out 
c[0] = 22 
c[1] = 11 
i    = 1122 
$
2