将char *转换为unsigned char *

时间:2011-08-04 11:00:31

标签: c char sha1 unsigned strcpy

如何在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摘要可以使用unsigned char进行最佳表示。

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

7 个答案:

答案 0 :(得分:11)

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

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

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

答案 1 :(得分:5)

你不能正确复制它,因为类型有所不同,编译器会警告你。

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

答案 2 :(得分: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)1malloc(20)。 如果你真的想要使用调用中每个元素的大小,请使用对象本身,就像我上面的代码一样。

答案 3 :(得分:1)

您可以将memcpy用作:

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

由于src和dest指针指向的基础对象类型与此函数无关。

答案 4 :(得分:0)

警告就是它所说的,你将一个unsigned char *摘要传递给strncpy函数,该函数与它预期的签名不同。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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