Подтвердить что ты не робот

Преобразование char * в unsigned char *

Как скопировать char * в unsigned char * правильно в C. Далее мой код

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

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

Я хотел бы скопировать массив char * в массив без знака char *. Я получаю следующее предупреждение, используя приведенный выше код

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

EDIT: добавление дополнительной информации. Моим требованием является то, что вызывающий агент передает SHA-дайджест главной функции в виде строки в командной строке, а основная функция внутренне сохраняет ее в дайджесте. SHA-дайджест может быть наилучшим образом представлен с использованием unsigned char.

Теперь уловка заключается в том, что я не могу изменить подпись основной функции (** char), потому что основная функция анализирует другие аргументы, которые она требует как char *, а не unsigned char *.

4b9b3361

Ответ 1

Чтобы избежать предупреждения компилятора, вам просто нужно:

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

Но избегать предупреждения компилятора часто не хорошая идея; он говорит вам, что существует фундаментальная несовместимость. В этом случае несовместимость состоит в том, что char имеет диапазон от -128 до +127 (обычно), тогда как unsigned char от 0 до +255.

Ответ 2

Вы не можете правильно скопировать его, так как есть разница в типах, компилятор предупреждает вас об этом.

Если вам нужно скопировать исходные биты массива argv[2], вы должны использовать функцию memcpy.

Ответ 3

Отключить подпись в вызове strncpy()

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

или ввести другую переменную

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

Также обратите внимание, что malloc(20 * sizeof(unsigned char*)), вероятно, не то, что вы хотите. Я думаю, вы хотите malloc(20 * sizeof(unsigned char)), или, как по определению sizeof (unsigned char), есть 1, malloc(20). Если вы действительно хотите использовать размер каждого элемента в вызове, используйте сам объект, как в моем коде выше.

Ответ 4

Вы можете использовать memcpy как:

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

поскольку основной тип объектов, на которые указывают указатели src и dest, не имеет значения для этой функции.

Ответ 5

Предупреждение - это просто то, что он говорит, вы передаете беззнаковый char * дайджест функции strncpy, которая отличается от той, которую она ожидает.

Ответ 6

Нет никакого способа конвертировать char * в unsigned char *. Они указывают на данные, и вы должны знать формат данных.

Для хэша SHA-1 существует как минимум 3 разных формата:

  • необработанный двоичный дайджест как массив из 20 октетов
  • дайджест как шестнадцатеричная строка, например "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
  • дайджест как строка Base64, например "5en6G6MezRroT3XKqkdPOmY/BfQ="

Ваш malloc(20 * sizeof(unsigned char)) имеет точный размер двоичного дайджеста, но слишком мал, чтобы соответствовать шестнадцатеричной строке или строке Base64. Я думаю, что unsigned char * указывает на двоичный дайджест.

Но char * пришел из аргументов командной строки main(), поэтому char *, вероятно, указывает на строку. Аргументы командной строки всегда являются строками C; они заканчиваются терминатором NUL '\0' и никогда не содержат '\0' в строке. Необработанные двоичные дайджесты могут содержать '\0', поэтому они не работают как аргументы командной строки.

Код для преобразования SHA-1-дайджеста из шестнадцатеричной строки в исходный двоичный файл может выглядеть как

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

Не используйте strncpy(dst, src, 20) для копирования исходных двоичных сводок. Функция strncpy (3) прекращает копирование, если находит '\0'; поэтому, если ваш дайджест содержит '\0', вы теряете часть дайджеста.