Konvertieren von char* in unsigned char*

Lesezeit: 6 Minuten

Benutzer-Avatar
Rajiv

Wie kopiere ich ein Zeichen * in ein Zeichen ohne Vorzeichen * korrekt in C. Im Folgenden ist mein Code

int main(int argc, char **argv)
{
    unsigned char *digest;

    digest = malloc(20 * sizeof(unsigned char));
    strncpy(digest, argv[2], 20);
    return 0;
}

Ich möchte das char*-Array korrekt in ein unsigniertes char*-Array kopieren. Ich erhalte die folgende Warnung mit dem obigen Code

warning: pointer targets in passing argument 1 of âstrncpyâ differ in signedness 

BEARBEITEN: Weitere Informationen hinzufügen. Meine Anforderung ist, dass der Aufrufer der Hauptfunktion einen SHA-Digest als Zeichenfolge in der Befehlszeile bereitstellt und die Hauptfunktion ihn intern im Digest speichert. SHA-Digest kann am besten mit einem unsigned char dargestellt werden.

Jetzt ist der Haken, dass ich die Signatur der Hauptfunktion (** char) nicht ändern kann, weil die Hauptfunktion andere Argumente analysiert, die sie als char* und nicht als unsigned char* benötigt.

  • Ein Hash-Digest wird normalerweise als ASCII-Darstellung des Hex-Werts des Digests ausgedrückt (z. B. “b6379dab2c...“). EIN char ist dafür absolut in Ordnung!

    – Oliver Charlesworth

    4. August 2011 um 11:24 Uhr

  • @oli Also im Grunde sollte der Cast auch ohne Probleme funktionieren strncpy((char*)digest, argv[2], 20); da wir es mit ASCII zu tun haben?

    – Rajiv

    4. August 2011 um 11:26 Uhr

  • @Rajiv: Es gibt zwei verschiedene Möglichkeiten, einen SHA-1-Digest darzustellen, der 160 Bit beträgt. Eine dieser Möglichkeiten besteht darin, 20 8-Bit-Bytes zu verwenden, und unsigned char ist die beste Art dafür. Die andere Möglichkeit besteht darin, eine ASCII-Darstellung zu verwenden, bei der jedes Zeichen eine hexadezimale Ziffer ist, die 4 Bits darstellt, und daher sind 40 davon erforderlich. Deutlich strncpy wird nicht zwischen ihnen konvertieren.

    – Steve Jessop

    4. August 2011 um 11:55 Uhr

  • @Steve: Ja, ich verwende die unsigned char-Version mit 20 8bits. Wenn strncpy dies nicht kann, würde memcpy oder eine andere Funktion den Zweck erfüllen?

    – Rajiv

    4. August 2011 um 14:34 Uhr

  • @Rajiv: Wie denkst du, wird der Benutzer diese 8-Bit-Werte am Terminal eingeben? Was ist, wenn einer von ihnen 0 ist?

    – Steve Jessop

    4. August 2011 um 15:05 Uhr


Um die Compiler-Warnung zu vermeiden, brauchen Sie nur:

strncpy((char *)digest, argv[2], 20);

Aber das Vermeiden der Compiler-Warnung ist oft nicht eine gute Idee; es sagt Ihnen, dass es eine grundlegende Inkompatibilität gibt. In diesem Fall ist die Inkompatibilität das char hat einen Bereich von -128 bis +127 (normalerweise), wohingegen unsigned char ist 0 bis +255.

  • Ja, das ist das Problem, wie löse ich die Inkompatibilität besser?

    – Rajiv

    4. August 2011 um 11:12 Uhr


  • Wenn Sie uns sagen könnten, warum Sie in als unsigned char benötigen, könnte uns das bei der Antwort helfen? Um eine bessere Lösung zu erraten, sollten Sie vielleicht eine Struktur oder Union anstelle eines Blobs aus unsigniertem Char-Speicher verwenden.

    – noelikus

    4. August 2011 um 11:32 Uhr

  • Im Falle des char * vs unsigned char *, die Warnung (die der Compiler laut Standard als Fehler behandeln soll!) weist selten auf einen Fehler hin, außer auf einen Fehler im Standard. Nahezu alle Standardfunktionen übernehmen char * sondern befassen sich mit Daten, die wirklich als Array von behandelt werden unsigned char. Sehen strcmp.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    4. August 2011 um 15:17 Uhr

  • @R ..: Was meinst du mit “als Array von behandelt unsigned char“?

    – Oliver Charlesworth

    4. August 2011 um 15:25 Uhr

  • Ich gab strcmp als Beispiel. Es ist erforderlich, seinen Vergleich basierend auf der Differenz zwischen den ersten nicht übereinstimmenden Bytes durchzuführen Interpretiert als unsigned char.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    4. August 2011 um 16:31 Uhr

Du kannst nicht korrekt Kopieren Sie es, da es Unterschiede in den Typen gibt, der Compiler warnt Sie genau davor.

Wenn Sie rohe Bits kopieren müssen argv[2] Array, das Sie verwenden sollten memcpy Funktion.

  • Mit memcpymüssen Sie zuerst die Länge von überprüfen argv[2] um den Zugriff auf Elemente außerhalb des Arrays zu vermeiden.

    – pmg

    4. August 2011 um 11:34 Uhr

Werfen Sie die Vorzeichen weg in die strncpy() Anruf

strncpy((char*)digest, argv[2], 20);

oder eine andere Variable einführen

#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
    unsigned char *digest;
    void *tmp;                   /* (void*) is compatible with both (char*) and (unsigned char*) */

    digest = malloc(20 * sizeof *digest);
    if (digest) {
        tmp = digest;
        if (argc > 2) strncpy(tmp, argv[2], 20);
        free(digest);
    } else {
        fprintf(stderr, "No memory.\n");
    }
    return 0;
}

Beachte das auch malloc(20 * sizeof(unsigned char*)) ist wahrscheinlich nicht das was du willst. Ich denke, du willst malloc(20 * sizeof(unsigned char))oder, wie per Definition sizeof (unsigned char) ist 1, malloc(20). Wenn Sie wirklich die Größe jedes Elements im Aufruf verwenden möchten, verwenden Sie das Objekt selbst, wie in meinem obigen Code.

  • IMO, hier eine Dummy-Variable einzuführen, verschleiert nur den Code, ohne entsprechenden Nutzen.

    – Oliver Charlesworth

    4. August 2011 um 11:22 Uhr

  • Das OP will offenbar einen “besseren Weg als einen Gips”. Das Verschleierte (void*) variable erreicht einen anderen Weg: Ich überlasse die Entscheidung, ob es besser ist, dem OP (wie Sie, @Oli, ich denke, es ist nicht so).

    – pmg

    4. August 2011 um 11:32 Uhr

Benutzer-Avatar
cyber_raj

Sie können memcpy verwenden als:

memcpy(digest, argv[2], strlen(argv[2]) + 1);

da die zugrunde liegenden Objekttypen, auf die src- und dest-Zeiger zeigen, für diese Funktion irrelevant sind.

Benutzer-Avatar
Georg Köhler

Es gibt nicht die eine Möglichkeit, umzuwandeln char * zu unsigned char *. Sie verweisen auf Daten, und Sie müssen das Format der Daten kennen.

Es gibt mindestens 3 verschiedene Formate für einen SHA-1-Hash:

  • den rohen binären Digest als ein Array von genau 20 Oktetten
  • der Digest als hexadezimaler String, wie "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
  • der Digest als Base64-String, wie "5en6G6MezRroT3XKqkdPOmY/BfQ="

Dein malloc(20 * sizeof(unsigned char)) hat die exakte Größe eines binären Digests, ist aber zu klein, um in eine hexadezimale Zeichenfolge oder eine Base64-Zeichenfolge zu passen. Ich vermute, dass die unsigned char * weist auf einen binären Digest hin.

Aber die char * kam aus den Kommandozeilenargumenten von main()also die char * deutet wahrscheinlich auf einen String hin. Befehlszeilenargumente sind immer C-Strings; sie enden mit dem NUL-Terminator '\0' und niemals enthalten '\0' in der Schnur. Rohe binäre Digests können enthalten '\0'sodass sie nicht als Befehlszeilenargumente funktionieren.

Der Code zum Konvertieren eines SHA-1-Digests von einer hexadezimalen Zeichenfolge in eine rohe Binärdatei könnte so aussehen

#include <stdio.h>
#include <stdlib.h>

unsigned char *
sha1_from_hex(char *hex)
{
    int i, m, n, octet;
    unsigned char *digest;

    digest = malloc(20);
    if (!digest)
        return NULL;

    for (i = 0; i < 20; i++) {
        sscanf(hex, " %n%2x%n", &m, &octet, &n);
        if (m != 0 || n != 2)
            goto fail;
        digest[i] = octet;
        hex += 2;
    }
    if (*hex)
        goto fail;
    return digest;

fail:
    free(digest);
    return NULL;
}

Nicht verwenden strncpy(dst, src, 20) um rohe binäre Digests zu kopieren. Das strncpy(3) Die Funktion stoppt das Kopieren, wenn sie eine findet '\0'; Also, wenn Ihr Digest enthält '\0'verlieren Sie einen Teil der Zusammenfassung.

Benutzer-Avatar
Stephan Rauch

Einfach setzen (char*) davor bzw (unsigned char*)

Benutzer-Avatar
BenMorel

Warnung ist einfach das, was es sagt, Sie übergeben einen unsignierten char * Digest an die strncpy-Funktion, die eine andere Vorzeichenbeschaffenheit aufweist als erwartet.

1296630cookie-checkKonvertieren von char* in unsigned char*

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

Privacy policy