21

如何在 C 中正确地将 char* 复制到 unsigned char*。以下是我的代码

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

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

我想正确地将 char* 数组复制到 unsigned char* 数组。我使用上面的代码收到以下警告

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

编辑:添加更多信息,我的要求是调用者在命令行上将 SHA 摘要作为字符串提供给主函数,并且主函数在内部将其保存在摘要中。SHA 摘要可以最好地使用无符号字符来表示。

现在的问题是我无法更改主函数的签名(** char),因为主函数解析它需要的其他参数为 char* 而不是 unsigned char*。

4

7 回答 7

15

为避免编译器警告,您只需要:

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

但是避免编译器警告通常不是一个好主意。它告诉你存在根本的不兼容。在这种情况下,不兼容char的范围是 -128 到 +127(通常),而unsigned char范围是 0 到 +255。

于 2011-08-04T11:09:23.827 回答
6

由于类型不同,您无法正确复制它,编译器会警告您。

如果您需要复制argv[2]数组的原始位,您应该使用memcpy函数。

于 2011-08-04T11:08:57.610 回答
2

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)。如果您真的想在调用中使用每个元素的大小,请使用对象本身,就像我上面的代码一样。

于 2011-08-04T11:15:34.920 回答
1

您可以将 memcpy 用作:

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

因为 src 和 dest 指针指向的对象的底层类型与此函数无关。

于 2011-08-04T11:21:02.900 回答
1

没有一种方法可以转换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',您将丢失部分摘要。

于 2017-09-23T05:05:32.430 回答
1

只需放在(char*)它前面或(unsigned char*)

于 2018-06-09T00:50:00.477 回答
0

警告就是它所说的,您正在将一个 unsigned char * 摘要传递给 strncpy 函数,该函数的符号与预期的不同。

于 2011-08-04T11:10:14.807 回答