Conversione di un int in un array di char a 4 byte (C)

Ehi, sto cercando di convertire un int che viene inserito dall’utente in 4 byte, che sto assegnando a un array di caratteri. Come si può fare?

Esempio:

Convertire un input utente di 175 a

00000000 00000000 00000000 10101111


Problema con tutte le risposte finora, la conversione di 255 dovrebbe risultare in 0 0 0 ff sebbene stampi come: 0 0 0 ffffffff

 unsigned int value = 255; buffer[0] = (value >> 24) & 0xFF; buffer[1] = (value >> 16) & 0xFF; buffer[2] = (value >> 8) & 0xFF; buffer[3] = value & 0xFF; union { unsigned int integer; unsigned char byte[4]; } temp32bitint; temp32bitint.integer = value; buffer[8] = temp32bitint.byte[3]; buffer[9] = temp32bitint.byte[2]; buffer[10] = temp32bitint.byte[1]; buffer[11] = temp32bitint.byte[0]; 

entrambi producono 0 0 0 ffffffff invece di 0 0 0 ff

Solo un altro esempio è 175 dato che l’input viene stampato come 0, 0, 0, ffffffaf quando dovrebbe essere solo 0, 0, 0, af

Il modo portatile per farlo (assicurandosi di ottenere 0x00 0x00 0x00 0xaf ovunque) è quello di utilizzare i turni:

 unsigned char bytes[4]; unsigned long n = 175; bytes[0] = (n >> 24) & 0xFF; bytes[1] = (n >> 16) & 0xFF; bytes[2] = (n >> 8) & 0xFF; bytes[3] = n & 0xFF; 

I metodi che usano i sindacati e memcpy() otterranno un risultato diverso su macchine diverse.


Il problema che stai avendo riguarda la stampa piuttosto che la conversione. Presumo che tu stia usando char piuttosto che unsigned char e stai usando una linea come questa per stamparla:

 printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]); 

Quando tutti i tipi più ristretti di int vengono passati a printf , vengono promossi a int (o unsigned int , se int non può contenere tutti i valori del tipo originale). Se char è firmato sulla tua piattaforma, allora 0xff probabilmente non rientra nell’intervallo di quel tipo ed è impostato su -1 invece (che ha la rappresentazione 0xff su una macchina a complemento 2s).

-1 è promosso a un int e ha la rappresentazione 0xffffffff come int sul tuo computer, e questo è ciò che vedi.

La tua soluzione è di utilizzare effettivamente il unsigned char , o di eseguire il cast di unsigned char printf :

 printf("%x %x %x %x\n", (unsigned char)bytes[0], (unsigned char)bytes[1], (unsigned char)bytes[2], (unsigned char)bytes[3]); 

Vuoi indirizzare i singoli byte di un int a 32 bit? Un ansible metodo è un’unione:

 union { unsigned int integer; unsigned char byte[4]; } foo; int main() { foo.integer = 123456789; printf("%u %u %u %u\n", foo.byte[3], foo.byte[2], foo.byte[1], foo.byte[0]); } 

Nota: corretto il printf per riflettere i valori non firmati.

Nella tua domanda hai dichiarato di voler convertire un input utente da 175 a 00000000 00000000 00000000 10101111 , che è il grande ordine di byte endian , noto anche come ordine di byte di rete .

Un modo per lo più portatile di convertire il vostro intero senza segno in un array di char non firmato big endian, come suggerito da quell’esempio “175” che avete dato, sarebbe quello di utilizzare la funzione htonl() di C (definita nell’intestazione su sistemi Linux) per convertire il tuo int unsigned in big endian byte order, quindi utilizzare memcpy() (definito nell’intestazione per C, per C ++) per copiare i byte nel tuo char (o unsigned char ) array.

La funzione htonl() accetta come argomento un numero intero a 32 bit senza segno (a differenza di htons() , che htons() un numero intero a 16 bit senza segno) e lo converte in ordine di byte di rete dall’ordine di byte dell’host (da qui l’acronimo , Host To Network Long, contro Host TO Network Abbreviazione di htons ), restituendo il risultato come numero intero a 32 bit senza segno. Lo scopo di questa famiglia di funzioni è garantire che tutte le comunicazioni di rete avvengano nell’ordine dei byte big endian, in modo che tutte le macchine possano comunicare tra loro su un socket senza problemi di ordine dei byte. (Per htonl() , per le macchine big-endian, le htonl() , htons() , ntohl() e ntohs() sono generalmente compilate per essere semplicemente un “no op”, perché i byte non devono essere capovolti prima che vengano inviati o ricevuti da un socket poiché sono già nell’ordine dei byte corretto)

Ecco il codice:

 #include  #include  #include  int main() { unsigned int number = 175; unsigned int number2 = htonl(number); char numberStr[4]; memcpy(numberStr, &number2, 4); printf("%x %x %x %x\n", numberStr[0], numberStr[1], numberStr[2], numberStr[3]); return 0; } 

Nota che, come ha detto caf, devi stampare i caratteri come caratteri senza segno usando l’identificatore di formato %x printf.

Il codice precedente stampa 0 0 0 af sulla mia macchina (una macchina x86_64, che usa un piccolo ordinamento di byte endian), che è esadecimale per 175.

Puoi provare:

 void CopyInt(int value, char* buffer) { memcpy(buffer, (void*)value, sizeof(int)); } 
 int a = 1; char * c = (char*)(&a); //In C++ should be intermediate cst to void* 

Perché avresti bisogno di un cast intermedio per annullare * in C ++ Perché cpp non consente la conversione diretta tra i puntatori, devi usare reinterpret_cast o cast per invalidare * fa la cosa.

Il problema con la conversione (il motivo per cui ti dà un ffffff alla fine) è perché il tuo intero esadecimale (che stai utilizzando l’operatore & binary con) viene interpretato come firmato. Trasmettilo su un numero intero senza segno e starai bene.

Un int è equivalente a uint32_t e char a uint8_t .

Mostrerò come ho risolto la comunicazione client-server, inviando il tempo reale (4 byte, formattato in epoca Unix) in un array a 1 bit, e poi ricostruito nell’altro lato. (Nota: il protocollo doveva inviare 1024 byte)

  • Dalla parte del cliente

     uint8_t message[1024]; uint32_t t = time(NULL); uint8_t watch[4] = { t & 255, (t >> 8) & 255, (t >> 16) & 255, (t >> 24) & 255 }; message[0] = watch[0]; message[1] = watch[1]; message[2] = watch[2]; message[3] = watch[3]; send(socket, message, 1024, 0); 
  • Lato server

     uint8_t res[1024]; uint32_t date; recv(socket, res, 1024, 0); date = res[0] + (res[1] << 8) + (res[2] << 16) + (res[3] << 24); printf("Received message from client %d sent at %d\n", socket, date); 

Spero che sia d'aiuto.

Il problema è che il char non firmato è un numero di 4 byte e non un numero di 1 byte come molti pensano, quindi cambialo

 union { unsigned int integer; char byte[4]; } temp32bitint; 

e cast durante la stampa, per impedire la promozione a ‘int’ (che C fa per impostazione predefinita)

 printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]); 

Non scriverò alcun codice. Basta dichiarare un puntatore int e assegnare l’indirizzo dell’array char ad esso. Quindi dì che qualunque cosa si trovi in ​​quel puntatore, la posizione è uguale al numero intero che vuoi convertire. Il compilatore si occupa di tutto il resto …