Hey, ich möchte ein vom Benutzer eingegebenes int in 4 Bytes konvertieren, das ich einem Zeichenarray zuordne. Wie kann das gemacht werden?
Beispiel:
Konvertieren Sie Benutzereingaben von 175 in
00000000 00000000 00000000 10101111
Bei Problemen mit allen bisherigen Antworten sollte die Konvertierung von 255 zu folgenden Ergebnissen führen 0 0 0 ff
: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];
beide ergeben 0 0 0 ffffffff
statt0 0 0 ff
Nur ein weiteres Beispiel ist 175, da die Eingabe so gedruckt wird, wie 0, 0, 0, ffffffaf
sie sein sollte0, 0, 0, af
%hhx
eine C99-Ergänzung ist.sizeof (int)
Bytes.memcpy
bei vorzeichenlosen Typen ist in Ordnung, wenn alle Typen vorzeichenlos sind und die Endianess berücksichtigt wurde. Gewerkschaftslösungen sind nicht in Ordnung, sie sind nicht portierbar - warum nicht portierbaren Code schreiben, wenn Sie mit dem gleichen Aufwand portablen Code erhalten können? Zeigerarithmetische Lösungen sind nicht in Ordnung, sie sind möglicherweise langsam, definitiv nicht portierbar und rufen häufig schlecht spezifiziertes Verhalten hervor.Antworten:
Der tragbare Weg, dies zu tun (um sicherzustellen, dass Sie
0x00 0x00 0x00 0xaf
überall hinkommen ), besteht darin, Schichten zu verwenden: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;
Die Methoden verwenden Gewerkschaften und
memcpy()
erhalten auf verschiedenen Maschinen ein unterschiedliches Ergebnis.Das Problem, das Sie haben, ist eher das Drucken als die Konvertierung. Ich nehme an, Sie verwenden
char
eher alsunsigned char
und Sie verwenden eine Zeile wie diese, um sie zu drucken:printf("%x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
Wenn Typen schmaler sind als
int
übergebenprintf
, werden sie heraufgestuftint
(oderunsigned int
, wennint
nicht alle Werte des ursprünglichen Typs gespeichert werden können). Wennchar
es auf Ihrer Plattform signiert ist,0xff
passt es wahrscheinlich nicht in den Bereich dieses Typs und wird stattdessen auf -1 gesetzt (was die Darstellung0xff
auf einem 2s-Komplement-Computer hat).-1 wird zu einem befördert
int
und hat die Darstellung0xffffffff
als einint
auf Ihrem Computer, und das sehen Sie.Ihre Lösung besteht darin, entweder tatsächlich zu verwenden
unsigned char
oderunsigned char
in derprintf
Anweisung zu verwenden:printf("%x %x %x %x\n", (unsigned char)bytes[0], (unsigned char)bytes[1], (unsigned char)bytes[2], (unsigned char)bytes[3]);
quelle
&
ist bitweises UND, was ein Ergebnis ergibt, bei dem jedes Bit 1 ist, wenn die entsprechenden Bits in beiden Operanden 1 sind.a & 0xFF
Dann ergibt sich ein Ergebnis, bei dem die niedrigsten 8 Bits mit den niedrigsten 8 Bits identischa
sind und die verbleibenden Bits alle Null.char
darf es breiter als 8 Bit sein (einige DSP-Programmierumgebungen weisen dies auf), sodass die Maske nur sicherstellt, dass in diesem Fall das Richtige passiert. Für den allgemeinen Fall wird es trotzdem optimiert.Möchten Sie die einzelnen Bytes eines 32-Bit-Int adressieren? Eine mögliche Methode ist eine Vereinigung:
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]); }
Hinweis: Der Druck wurde korrigiert, um vorzeichenlose Werte wiederzugeben.
quelle
In Ihrer Frage haben Sie angegeben, dass Sie eine Benutzereingabe von 175 in konvertieren möchten. Dies
00000000 00000000 00000000 10101111
ist eine Big-Endian- Bytereihenfolge, die auch als Netzwerkbyte-Reihenfolge bezeichnet wird .Eine meist portable Möglichkeit, Ihre vorzeichenlose Ganzzahl in ein vorzeichenloses Big-Endian-Zeichen-Array zu konvertieren, wie Sie aus dem von Ihnen angegebenen Beispiel "175" vorgeschlagen haben, besteht darin, die
htonl()
Funktion von C (im Header<arpa/inet.h>
auf Linux-Systemen definiert) zu verwenden, um Ihr vorzeichenloses int in zu konvertieren Big-Endian-Bytereihenfolge, dann verwenden Siememcpy()
(definiert im Header<string.h>
für C,<cstring>
für C ++), um die Bytes in Ihr char-Array (oder vorzeichenloses char-Array) zu kopieren.Die
htonl()
Funktion verwendet eine vorzeichenlose 32-Bit-Ganzzahl als Argument (im Gegensatz zuhtons()
einer vorzeichenlosen 16-Bit-Ganzzahl) und konvertiert sie in die Netzwerkbyte-Reihenfolge aus der Host-Byte-Reihenfolge (daher das Akronym Host TO Network Long,). versus Host TO Network Short forhtons
), wobei das Ergebnis als vorzeichenlose 32-Bit-Ganzzahl zurückgegeben wird. Der Zweck dieser Funktionsfamilie besteht darin, sicherzustellen, dass die gesamte Netzwerkkommunikation in der Big-Endian-Bytereihenfolge erfolgt, sodass alle Maschinen über einen Socket ohne Probleme mit der Bytereihenfolge miteinander kommunizieren können. (Nebenbei bemerkt, für Big-Endian - Maschinen, diehtonl()
,htons()
,ntohl()
undntohs()
Funktionen werden im Allgemeinen nur als "no op" kompiliert, da die Bytes nicht umgedreht werden müssen, bevor sie gesendet oder von einem Socket empfangen werden, da sie bereits in der richtigen Bytereihenfolge vorliegen.Hier ist der Code:
#include <stdio.h> #include <arpa/inet.h> #include <string.h> 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; }
Beachten Sie, dass Sie, wie im Café erwähnt, die Zeichen mit dem Formatbezeichner von printf als vorzeichenlose Zeichen drucken müssen
%x
.Der obige Code wird
0 0 0 af
auf meinem Computer gedruckt (einem x86_64-Computer, der eine kleine Endian-Bytereihenfolge verwendet), der für 175 hexadezimal ist.quelle
Du kannst es versuchen:
void CopyInt(int value, char* buffer) { memcpy(buffer, (void*)value, sizeof(int)); }
quelle
char
für Bytes verwenden, verwendenuint8_t
.(void*)value
ist einfach falsch, sollte sein&value
.Warum benötigen Sie eine Zwischenbesetzung, um * in C ++ ungültig zu machen? Da cpp keine direkte Konvertierung zwischen Zeigern zulässt, müssen Sie reinterpret_cast oder eine Umwandlung verwenden, um * zu stornieren.
quelle
int a = 1; char * c = (char*)(&a); //In C++ should be intermediate cst to void*
quelle
void *
in C ++?Das Problem bei der Konvertierung (der Grund, warum Sie am Ende ein ffffff erhalten) ist, dass Ihre hexadezimale Ganzzahl (mit der Sie den Operator & binary verwenden) als signiert interpretiert wird. Wenn Sie es in eine vorzeichenlose Ganzzahl umwandeln, ist alles in Ordnung.
quelle
An
int
ist äquivalent zuuint32_t
undchar
zuuint8_t
.Ich werde zeigen, wie ich die Client-Server-Kommunikation aufgelöst, die tatsächliche Zeit (4 Byte, formatiert in der Unix-Epoche) in einem 1-Bit-Array gesendet und dann auf der anderen Seite neu erstellt habe. (Hinweis: Das Protokoll sollte 1024 Bytes senden.)
Client-Seite
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);
Serverseite
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);
Ich hoffe es hilft.
quelle
Das Problem tritt auf, da vorzeichenloses Zeichen eine 4-Byte-Zahl ist, keine 1-Byte-Zahl, wie viele denken. Ändern Sie sie daher in
union { unsigned int integer; char byte[4]; } temp32bitint;
und während des Druckens gegossen, um zu verhindern, dass auf 'int' hochgestuft wird (was C standardmäßig tut)
printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]);
quelle
Sie können einfach
memcpy
wie folgt verwenden:unsigned int value = 255; char bytes[4] = {0, 0, 0, 0}; memcpy(bytes, &value, 4);
quelle