web-dev-qa-db-fra.com

Conversion de caractère * en caractère non signé *

Comment copier correctement un caractère * dans un caractère non signé * en C. Voici mon code 

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

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

Je voudrais copier correctement char * array sur unsigned char * array. Je reçois l'avertissement suivant en utilisant le code ci-dessus 

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

EDIT: Ajout de plus d’informations. Mon appelant doit impérativement fournir un condensé SHA à la fonction principale sous forme de chaîne sur la ligne de commande et la sauvegarder en interne dans le résumé. SHA Le résumé peut être mieux représenté à l'aide d'un caractère non signé.

Maintenant, le problème est que je ne peux pas changer la signature de la fonction principale (** char) car celle-ci analyse d'autres arguments dont elle a besoin comme char * et non unsigned char *.

18
Rajiv

Pour éviter l'avertissement du compilateur, vous avez simplement besoin de:

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

Mais éviter l’avertissement du compilateur est souvent pas une bonne idée; cela vous dit qu'il y a une incompatibilité fondamentale. Dans ce cas, l'incompatibilité est que char a une plage allant de -128 à +127 (en général), alors que unsigned char est compris entre 0 et +255.

11

Vous ne pouvez pas correctement copier car il y a une différence de types, le compilateur vous en avertit.

Si vous devez copier des bits bruts du tableau argv[2], vous devez utiliser la fonction memcpy.

5
Petr Abdulin

Jeter la signature dans l'appel strncpy()

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

ou introduire une autre variable

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

Notez également que malloc(20 * sizeof(unsigned char*)) n’est probablement pas ce que vous voulez. Je pense que vous voulez malloc(20 * sizeof(unsigned char)) ou, comme par définition sizeof (unsigned char) est 1, malloc(20). Si vous voulez vraiment utiliser la taille de chaque élément de l'appel, utilisez l'objet lui-même, comme dans mon code ci-dessus.

2
pmg

Vous pouvez utiliser memcpy comme:

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

comme le type sous-jacent d'objets pointés par les pointeurs src et dest ne sont pas pertinents pour cette fonction.

1
cyber_raj

Il n’existe pas un moyen unique de convertir char * en unsigned char *. Ils pointent sur des données et vous devez connaître le format de ces données.

Il existe au moins 3 formats différents pour un hachage SHA-1:

  • le résumé binaire brut sous la forme d'un tableau contenant exactement 20 octets
  • le résumé sous forme de chaîne hexadécimale, telle que "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
  • le résumé sous forme de chaîne Base64, telle que "5en6G6MezRroT3XKqkdPOmY/BfQ="

Votre malloc(20 * sizeof(unsigned char)) a la taille exacte d'un résumé binaire, mais est trop petit pour contenir une chaîne hexadécimale ou une chaîne Base64. Je suppose que le unsigned char * pointe vers un condensé binaire.

Mais le char * provient des arguments de la ligne de commande de main(); le char * pointe donc probablement sur une chaîne. Les arguments de ligne de commande sont toujours des chaînes C; ils se terminent par le terminateur NUL '\0' et ne contiennent jamais '\0' dans la chaîne. Les condensés binaires bruts peuvent contenir '\0', ils ne fonctionnent donc pas comme arguments de ligne de commande.

Le code permettant de convertir un condensé SHA-1 de chaîne hexadécimale en binaire brut pourrait ressembler à

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

N'utilisez pas strncpy(dst, src, 20) pour copier des résumés binaires bruts. La fonction strncpy (3) arrête la copie si elle trouve un '\0'; Par conséquent, si votre résumé contient '\0', vous en perdez une partie.

0
George Koehler

Il suffit de mettre (char*) devant lui Ou (unsigned char*)

0
Johnny camargo

Warning est simplement ce qui est écrit, vous passez un caractère * non signé à une fonction strncpy dont la signature est différente de celle attendue. 

0
Sandeep Pathak