Konvertieren eines int in ein 4-Byte-Char-Array (C)

Lesezeit: 6 Minuten

Benutzeravatar von Jacob Nelson
Jacob Nelson

Hey, ich möchte ein vom Benutzer eingegebenes Int in 4 Bytes umwandeln, die ich einem Zeichenarray zuweise. Wie kann dies geschehen?

Beispiel:

Wandeln Sie eine Benutzereingabe von 175 um

00000000 00000000 00000000 10101111


Problem mit allen bisherigen Antworten, die Konvertierung von 255 sollte dazu führen 0 0 0 ff obwohl es ausgedruckt wird als: 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];

beides ergibt 0 0 0 ffffffff Anstatt von 0 0 0 ff

Ein weiteres Beispiel ist 175, da die Eingabe als ausgedruckt wird 0, 0, 0, ffffffaf wenn es gerade sein soll 0, 0, 0, af

  • Wie ist dein Puffer[] definiert? Bei einem vorzeichenlosen Byte mit einem Wert größer als 127 ist das höchstwertige Bit gesetzt. Dies bedeutet eine negative Zahl, wenn ein vorzeichenbehaftetes Byte verwendet wird. Ihr FFFFFFFF sieht aus wie eine vorzeichenerweiterte Interpretation eines 0xFF-Bytes.

    – Hochofen

    24. September 2010 um 6:16 Uhr

  • Sie sollten das Format %hhx verwenden, um Ihre Zahlen zu drucken.

    – Jens Gustedt

    24. September 2010 um 6:22 Uhr

  • ..aber beachte das %hhx ist eine C99-Ergänzung.

    – Café

    24. September 2010 um 6:40 Uhr

  • Nit: Sie haben keine Garantie, dass 4 Bytes notwendig und ausreichend sind, um ein int zu halten. Du brauchst sizeof (int) Bytes.

    – pmg

    24. September 2010 um 8:33 Uhr

  • Für diejenigen, die auf diesen Beitrag stoßen könnten: Die einzig richtige Lösung besteht darin, die Bitverschiebung für nicht signierte Typen wie in der akzeptierten Antwort zu verwenden. Sie können das lesen und dort aufhören. Es ist sowohl die schnellste als auch die portabelste Version. memcpy on unsigned types ist ok, wenn alle Typen unsigned sind und Endianess berücksichtigt wurde. Gewerkschaftslösungen sind nicht in Ordnung, sie sind nicht portierbar – warum nicht portierbaren Code schreiben, wenn Sie mit demselben Aufwand portierbaren Code erhalten können? Zeigerarithmetische Lösungen sind nicht in Ordnung, sie sind möglicherweise langsam, definitiv nicht portierbar und rufen oft schlecht spezifiziertes Verhalten hervor.

    – Ludin

    13. März 2019 um 13:53 Uhr


Benutzeravatar von caf
Café

Das tragbar Weg, dies zu tun (sicherzustellen, dass Sie bekommen 0x00 0x00 0x00 0xaf überall) ist die Verwendung von Schichten:

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, die Vereinigungen und verwenden memcpy() wird auf verschiedenen Rechnern ein anderes Ergebnis erhalten.


Das Problem, das Sie haben, liegt eher beim Drucken als bei der Konvertierung. Ich nehme an, Sie verwenden char statt unsigned charund 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 alle Arten schmaler als int werden weitergegeben printfzu denen sie befördert werden int (oder unsigned intwenn int kann nicht alle Werte des ursprünglichen Typs aufnehmen). Wenn char ist dann auf Ihrer Plattform unterschrieben 0xff passt wahrscheinlich nicht in den Bereich dieses Typs und wird stattdessen auf -1 gesetzt (was die Darstellung hat 0xff auf einem 2er-Komplement-Automaten).

-1 wird zu einem befördert intund hat die Vertretung 0xffffffff als ein int auf Ihrem Computer, und das ist, was Sie sehen.

Ihre Lösung besteht darin, entweder tatsächlich zu verwenden unsigned charoder andernfalls in umwandeln unsigned char in dem printf Aussage:

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

  • @jacobnlsn: Es ist ein Problem mit der Art und Weise, wie Sie es drucken, siehe Update.

    – Café

    24. September 2010 um 6:14 Uhr


  • ZerOne: & ist ein bitweises UND, das ein Ergebnis liefert, bei dem jedes Bit 1 ist, wenn die entsprechenden Bits in beiden Operanden 1 sind. a & 0xFF gibt dann ein Ergebnis aus, bei dem die niedrigsten 8 Bits die gleichen sind wie die niedrigsten 8 Bits in aund die verbleibenden Bits sind alle Null.

    – Café

    6. September 2016 um 11:56 Uhr

  • @rem: Obwohl ungewöhnlich, char darf 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 Normalfall wird es trotzdem optimiert.

    – Café

    17. Oktober 2017 um 5:34 Uhr

  • @ user143252: Das ist jedoch genau das, wonach die ursprüngliche Frage gefragt hat.

    – Café

    29. März 2021 um 0:04 Uhr

  • @ user143252: Sicher, aber das wollte die Person, die diese Frage stellt, nicht.

    – Café

    30. März 2021 um 13:31 Uhr

Benutzeravatar von Blastfurnace
Hochofen

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: printf korrigiert, um vorzeichenlose Werte widerzuspiegeln.

  • Meine Frage wurde bearbeitet, damit Sie das Problem sehen können, das ich mit Ihrer Lösung habe.

    – Jakob Nelson

    24. September 2010 um 5:58 Uhr

  • Ich würde uint32_t anstelle von int schreiben, nur um mir keine Gedanken über 32- oder 64-Bit-Maschinen zu machen.

    – Tadeusz A. Kadłubowski

    24. September 2010 um 6:16 Uhr

  • Achten Sie darauf, dass Sie es nicht mit undefiniertem Verhalten zu tun haben. stackoverflow.com/questions/11639947

    – bzeaman

    4. November 2014 um 9:48 Uhr

Benutzeravatar von villapx
villapx

In Ihrer Frage haben Sie angegeben, dass Sie eine Benutzereingabe von 175 bis konvertieren möchten
00000000 00000000 00000000 10101111welches ist Big-Endian Bytereihenfolge, auch bekannt als Netzwerk-Byte-Reihenfolge.

Eine größtenteils portable Methode zum Konvertieren Ihrer vorzeichenlosen Ganzzahl in ein Big-Endian-Zeichenarray ohne Vorzeichen, wie Sie anhand des von Ihnen angegebenen Beispiels “175” vorgeschlagen haben, wäre die Verwendung von Cs htonl() Funktion (definiert im Header <arpa/inet.h> auf Linux-Systemen), um Ihr unsigned int in die Big-Endian-Byte-Reihenfolge zu konvertieren, und verwenden Sie dann memcpy() (in der Kopfzeile definiert <string.h> für C, <cstring> für C++), um die Bytes in Ihr char-Array (oder unsigned char) zu kopieren.

Das htonl() -Funktion akzeptiert eine vorzeichenlose 32-Bit-Ganzzahl als Argument (im Gegensatz zu htons()die eine vorzeichenlose 16-Bit-Ganzzahl aufnimmt) und konvertiert sie aus der Host-Byte-Reihenfolge in die Netzwerk-Byte-Reihenfolge (daher das Akronym Host TO Network Long im Vergleich zu Host TO Network Short for). htons) und gibt das Ergebnis als vorzeichenlose 32-Bit-Ganzzahl zurück. Der Zweck dieser Funktionsfamilie besteht darin, sicherzustellen, dass die gesamte Netzwerkkommunikation in Big-Endian-Byte-Reihenfolge erfolgt, sodass alle Computer ohne Byte-Reihenfolge-Probleme über einen Socket miteinander kommunizieren können. (Nebenbei, für Big-Endian-Maschinen ist die htonl(), htons(), ntohl() und ntohs() Funktionen werden im Allgemeinen so kompiliert, dass sie nur eine “No-Op” sind, da die Bytes nicht umgedreht werden müssen, bevor sie über einen Socket gesendet oder von einem Socket empfangen werden, da sie bereits in der richtigen Byte-Reihenfolge sind.)

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 caf sagte, die Zeichen als drucken müssen ohne Vorzeichen Zeichen mit printf’s %x Formatbezeichner.

Der obige Code wird gedruckt 0 0 0 af auf meinem Rechner (einem x86_64-Rechner, der die Little-Endian-Byte-Reihenfolge verwendet), was Hex für 175 ist.

Du kannst es versuchen:

void CopyInt(int value, char* buffer) {
  memcpy(buffer, (void*)value, sizeof(int));
}

Warum brauchen Sie in C++ eine Zwischenumwandlung in void*?

Benutzeravatar von gandjustas
Gandjustas

int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*

Benutzeravatar von Enusi
Enusi

Das Problem bei der Konvertierung (der Grund, warum Sie am Ende ein ffffff erhalten) besteht darin, dass Ihre Hex-Ganzzahl (mit der Sie den Binäroperator & verwenden) als signiert interpretiert wird. Wandeln Sie es in eine vorzeichenlose Ganzzahl um, und Sie werden in Ordnung sein.

1419740cookie-checkKonvertieren eines int in ein 4-Byte-Char-Array (C)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy