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 *.
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.
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
.
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.
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.
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:
"e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
"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.
Il suffit de mettre (char*)
devant lui Ou (unsigned char*)
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.