web-dev-qa-db-fra.com

Stocker un int dans un tableau de caractères?

Je veux stocker un int de 4 octets dans un tableau de caractères ... tel que les 4 premiers emplacements du tableau de caractères soient les 4 octets du entier.

Ensuite, je veux retirer l’intérieur du tableau ...

Aussi, des points bonus si quelqu'un peut me donner du code pour le faire en boucle ... IE en écrivant comme 8 ints dans un tableau de 32 octets.

int har = 0x01010101;
char a[4];
int har2;

// write har into char such that:
// a[0] == 0x01, a[1] == 0x01, a[2] == 0x01, a[3] == 0x01 etc.....

// then, pull the bytes out of the array such that:
// har2 == har

Merci les gars!

EDIT: Supposer que int sont 4 octets ... 

EDIT2: S'il vous plaît ne vous souciez pas de l'endianité ... Je vais me soucier de l'endianité. Je veux juste différentes façons d’atteindre ce qui précède en C/C++. Merci

EDIT3: Si vous ne le savez pas, j'essaie d'écrire une classe de sérialisation au bas niveau ... alors je recherche différentes stratégies pour sérialiser certains types de données courants.

19
Polaris878

Ce n’est pas le moyen le plus optimal, mais c’est un coffre fort.


int har = 0x01010101;
char a[4];
a[0] = har & 0xff;
a[1] = (har>>8)  & 0xff;
a[2] = (har>>16) & 0xff;
a[3] = (har>>24) & 0xff;
22
user184677

Sauf si vous vous souciez de l'ordre des octets, memcpy fera l'affaire:

memcpy(a, &har, sizeof(har));
...
memcpy(&har2, a, sizeof(har2));

Bien sûr, il n’existe aucune garantie que sizeof(int)==4 s’applique à une implémentation particulière (et il existe des implémentations du monde réel pour lesquelles cela est en fait faux).

Écrire une boucle devrait être trivial à partir d'ici.

39
Pavel Minaev
int main() {
    typedef union foo {
        int x;
        char a[4];
    } foo;

    foo p;
    p.x = 0x01010101;
    printf("%x ", p.a[0]);
    printf("%x ", p.a[1]);
    printf("%x ", p.a[2]);
    printf("%x ", p.a[3]);

    return 0;
}

N'oubliez pas que le a [0] contient le LSB et le [3] le MSB, sur une petite machine endian.

8
Ashwin
#include <stdio.h>

int main(void) {
    char a[sizeof(int)];
    *((int *) a) = 0x01010101;
    printf("%d\n", *((int *) a));
    return 0;
}

Garder en tete:

Un pointeur sur un objet ou un type incomplet peut être converti en un pointeur sur un autre type d'objet ou incomplet. Si le pointeur résultant n'est pas correctement aligné pour le fichier pointé sur le type, le comportement est indéfini.

8
Sinan Ünür

Remarque: L’accès à une union par un élément qui n’était pas le dernier attribué à un comportement indéfini . caractère si

char arr[4];
int a = 5;

arr[3] = a & 0xff;
arr[2] = (a & 0xff00) >>8;
arr[1] = (a & 0xff0000) >>16;
arr[0] = (a & 0xff000000)>>24;

obligerait arr [0] à conserver l'octet le plus significatif et arr [3] le moins. 

edit: Juste pour que vous compreniez le tour & c'est un peu sage 'et' où && est logique 'et' . Merci aux commentaires sur le décalage oublié.

8
stonemetal

N'utilisez pas les syndicats, précise Pavel:

C'est U.B., parce que C++ interdit accéder à un membre du syndicat autre que le dernier qui a été écrit à. Dans En particulier, le compilateur est libre de optimiser l’affectation à int membre complètement avec le code ci-dessus, puisque sa valeur n'est pas utilisé ultérieurement (il ne voit que le suivant lu pour le membre char[4] et n’a aucune obligation de lui donner une valeur significative) . En pratique, g ++ en particulier est connu pour tirer de telles astuces, alors ceci ce n'est pas que de la théorie. D'autre part, en utilisant static_cast<void*> suivi de static_cast<char*> est garanti à travail.

- Pavel Minaev 

7
GManNickG

Vous pouvez également utiliser le placement new pour cela:

void foo (int i) {
  char * c = new (&i) char[sizeof(i)];
}
4
Richard Corden

 #include <stdint.h> 

 int main (int argc, char * argv []) {
/* 8 ints dans une boucle */
 int i; 
 int * intPtr 
 int intArr [8] = {1, 2, 3, 4, 5, 6, 7, 8}; 
 char * charArr = malloc (32); 

 pour (i = 0; i <8; i ++) {
 intPtr = (int *) & (charArr [i * 4]); 
/* ^ ^ ^ ^ */
/* pointe sur | | | */
/* cast as int * | | */
/* Adresse de | */
/* Emplacement dans le tableau de caractères */

 * intPtr = intArr [i];/* write int à l’emplacement indiqué */
 } 

/* Lire ints */
 pour (i = 0; i <8; i ++) {
 intPtr = (int *) & (charArr [i * 4]); 
 intArr [i] = * intPtr; 
 } 

 char * myArr = malloc (13); 
 int myInt; 
 uint8_t * p8;/* nombre entier non signé de 8 bits */
 uint16_t * p16;/* nombre entier non signé de 16 bits */
 uint32_t * p32;/* nombre entier non signé de 32 bits */

/* Utilisation de tailles autres que les 4 octets, */
/* définit tous les bits de myArr sur 1 */
 p8 = (uint8_t *) & (myArr [0]); 
 p16 = (uint16_t *) & (myArr [1]); 
 p32 = (uint32_t *) & (myArr [5]); 
 * p8 = 255; 
 * p16 = 65535; 
 * p32 = 4294967295; 

/* Récupère les valeurs */
 p16 = (uint16_t *) & (myArr [1]); 
 uint16_t my16 = * p16; 

/* Mettez le 16 bit int dans un int */.__ régulier. myInt = (int) my16; 

 } 

2
Schlameel
char a[10];
int i=9;

a=boost::lexical_cast<char>(i)

trouvé que c’est le meilleur moyen de convertir char en int et vice-versa. 

une alternative à boost :: lexical_cast est sprintf.

char temp[5];
temp[0]="h"
temp[1]="e"
temp[2]="l"
temp[3]="l"
temp[5]='\0'
sprintf(temp+4,%d",9)
cout<<temp;

la sortie serait: hell9

1
pari
 valeur syndicale {
 int i; 
 char octets [sizof (int)]; 
}; 

 valeur v; 
 v.i = 2; 

 char * octets = v.bytes; 
0
codie