it-swarm.com.de

Ein Int in einem Char-Array speichern?

Ich möchte ein 4-Byte-Int in einem Char-Array speichern ... so dass die ersten 4 Stellen des Char-Arrays die 4 Bytes des Int sind.

Dann möchte ich die int wieder aus dem Array ziehen ...

Außerdem Bonuspunkte, wenn mir jemand Code geben kann, der dies in einer Schleife ausführt ... IE indem er 8 Zoll in ein 32-Byte-Array schreibt.

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

Danke Leute!

EDIT: Angenommen, int sind 4 Bytes ...

EDIT2: Bitte kümmern Sie sich nicht um Endianness ... Ich werde über Endianness sorgen. Ich möchte nur verschiedene Möglichkeiten, um das oben genannte in C/C++ zu erreichen. Vielen Dank

EDIT3: Wenn Sie nicht sagen können, ich versuche, eine Serialisierungsklasse auf der niedrigen Ebene zu schreiben ... also suche ich nach verschiedenen Strategien, um einige gemeinsame Datentypen zu serialisieren.

19
Polaris878

Nicht der optimalste Weg, ist aber endian sicher.


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

Wenn Sie sich nicht für die Reihenfolge der Bytes und dergleichen interessieren, wird memcpy den Trick ausführen:

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

Natürlich gibt es keine Garantie, dass sizeof(int)==4 für eine bestimmte Implementierung gilt (und es gibt realistische Implementierungen, für die dies tatsächlich falsch ist).

Das Schreiben einer Schleife sollte von hier aus trivial sein.

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;
}

Beachten Sie, dass a [0] das LSB und a [3] das MSB auf einer Little-Endian-Maschine enthält.

8
Ashwin
#include <stdio.h>

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

Merken Sie sich:

Ein Zeiger auf ein Objekt oder einen unvollständigen Typ kann in einen Zeiger auf ein anderes Objekt oder einen unvollständigen Typ konvertiert werden. Wenn der resultierende Zeiger für den Typ , Auf den gezeigt wird, nicht korrekt ausgerichtet ist, ist das Verhalten undefiniert.

8
Sinan Ünür

Hinweis: Der Zugriff auf eine Union über ein Element, dem nicht das letzte Element zugewiesen wurde, ist undefiniertes Verhalten. (Vorausgesetzt, eine Plattform, auf der Zeichen 8 Bit und ints 4 Bytes enthalten) Eine Bitmaske von 0xFF wird ein Zeichen so maskieren

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;

würde arr [0] das höchstwertige Byte und arr [3] das niedrigste halten. 

edit: Nur damit du den Trick verstehst & etwas weise 'und' wo && ist logisch 'und'. Danke an die Kommentare zur vergessenen Schicht.

8
stonemetal

Verwenden Sie keine Gewerkschaften, Pavel klärt:

Es ist U.B., weil C++ den Zugriff auf ein anderes Gewerkschaftsmitglied als Untersagt, auf das zuletzt geschrieben wurde. Insbesondere in Steht es dem Compiler frei, Die Zuordnung zu int Member vollständig mit dem Code Oben zu optimieren, da sein Wert nicht Ist. .] anschließend verwendet (es wird nur der nachfolgende -Lesen für das char[4] -Mitglied angezeigt, und es besteht keine Verpflichtung, dort einen sinnvollen Wert anzugeben). In der Praxis g ++ ist insbesondere dafür bekannt, solche Tricks zu ziehen, also ist nicht nur Theorie. Andererseits ist Mit static_cast<void*> gefolgt von static_cast<char*> garantiert, dass Funktioniert.

- Pavel Minaev 

7
GManNickG

Sie können hierfür auch eine neue Platzierung verwenden:

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 in eine Schleife */
 int i; 
 int * intPtr 
 int intArr [8] = {1, 2, 3, 4, 5, 6, 7, 8}; 
 char * charArr = malloc (32); 
 
 für (i = 0; i <8; i ++) {
 intPtr = (int *) & (charArr.) [i * 4]); 
/* ^ ^ ^ ^ */
/* Punkt auf | | | */
/* umgewandelt als int * | | */
/* Adresse von | */
/* Position im Zeichenarray */
 
 * IntPtr = intArr [i];/* Schreibe int an Stelle, die auf */
} 
 
 steht./* Einlesen von */
 für (i = 0; i <8; i ++) {
 intPtr = (int *) & (charArr [i * 4]); 
 intArr [i] = * intPtr; 
} 
 
. ] char * myArr = malloc (13); 
 int myInt; 
 uint8_t * p8;/* vorzeichenlose 8-Bit-Ganzzahl */
 uint16_t * p16;/* vorzeichenlose 16-Bit-Ganzzahl */
 uint32_t * p32;/* vorzeichenlose 32-Bit-Ganzzahl */
 
/* Bei Verwendung von anderen Größen als 4-Byte-Ints setzen */
/* alle Bits in myArr auf 1 */
 p8 = (uint8_t *) & (myArr [0]); 
 p16 = (uint16_t *) & (myArr [1]); 
 p32 = (uint32_t *) & (myArr.) [5]); 
 * P8 = 255; 
 * P16 = 65535; 
 * P32 = 4294967295; 
 
/* Ermitteln Sie die Werte back out */
 p16 = (uint16_t *) & (meinArr [1]); 
 uint16_t mein16 = * p16; 
 
/* Setzen Sie das 16-Bit int in ein reguläres int */
 myInt = (int) my16; 
 
} 
 
2
Schlameel
char a[10];
int i=9;

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

dies ist der beste Weg, Char in Int und umgekehrt zu konvertieren. 

alternative zu boost :: lexical_cast ist 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;

ausgabe wäre: hell9

1
pari
 Vereinigungswert {[.___.] int i; 
 Zeichen Bytes [sizeof (int)]; 
}; 
 
 Wert v; 
 vi = 2; 
 
 char * bytes = v.bytes; 
0
codie