简体   繁体   English

将char *转换为unsigned char *

[英]Converting char* to unsigned char*

How do I copy a char* to a unsigned char* correctly in C. Following is my code 如何在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;
}

I would like to correctly copy char* array to unsigned char* array. 我想正确地将char *数组复制到unsigned char *数组。 I get the following warning using the above code 我使用上面的代码得到以下警告

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

EDIT : Adding more information, My requirement is that the caller provide a SHA digest to the main function as a string on command line and the main function internally save it in the digest. 编辑 :添加更多信息,我的要求是调用者在主函数中提供SHA摘要作为命令行上的字符串,主函数在内部将其保存在摘要中。 SHA digest can be best represented using a unsigned char. SHA摘要可以使用unsigned char最好地表示。

Now the catch is that I can't change the signature of the main function (** char) because the main function parses other arguments which it requires as char* and not unsigned char*. 现在的问题是我无法更改main函数(** char)的签名,因为main函数解析了它需要的其他参数作为char *而不是unsigned char *。

To avoid the compiler warning, you simply need: 要避免编译器警告,您只需要:

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

But avoiding the compiler warning is often not a good idea; 但是避免编译器警告往往不是一个好主意; it's telling you that there is a fundamental incompatibility. 它告诉你,存在根本的不兼容性。 In this case, the incompatibility is that char has a range of -128 to +127 (typically), whereas unsigned char is 0 to +255. 在这种情况下,不兼容性是char的范围是-128到+127(通常),而unsigned char是0到+255。

You can't correctly copy it since there is difference in types, compiler warns you just about that. 您无法正确复制它,因为类型有所不同,编译器会警告您。

If you need to copy raw bits of argv[2] array you should use memcpy function. 如果你需要复制argv[2]数组的原始位,你应该使用memcpy函数。

Cast the signedness away in the strncpy() call strncpy()调用中抛出签名

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

or introduce another 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;
}

Also note that malloc(20 * sizeof(unsigned char*)) is probably not what you want. 另请注意, malloc(20 * sizeof(unsigned char*))可能不是您想要的。 I think you want malloc(20 * sizeof(unsigned char)) , or, as by definition sizeof (unsigned char) is 1 , malloc(20) . 我想你想要malloc(20 * sizeof(unsigned char)) ,或者,如定义sizeof (unsigned char)1malloc(20) If you really want to use the size of each element in the call, use the object itself, like in my code above. 如果你真的想要使用调用中每个元素的大小,请使用对象本身,就像我上面的代码一样。

You can use memcpy as: 您可以使用memcpy:

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

as the underlying type of objects pointed to by src and dest pointers are irrelevant for this function. 因为src和dest指针指向的基础对象类型与此函数无关。

There is no one way to convert char * to unsigned char * . 没有一种方法可以将char *转换为unsigned char * They point to data, and you must know the format of the data. 它们指向数据,您必须知道数据的格式。

There are at least 3 different formats for a SHA-1 hash: SHA-1哈希至少有3种不同的格式:

  • the raw binary digest as an array of exactly 20 octets 原始二进制摘要作为正好20个八位字节的数组
  • the digest as a hexadecimal string, like "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4" 摘要为十六进制字符串,如"e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
  • the digest as a Base64 string, like "5en6G6MezRroT3XKqkdPOmY/BfQ=" 摘要为Base64字符串,如"5en6G6MezRroT3XKqkdPOmY/BfQ="

Your malloc(20 * sizeof(unsigned char)) has the exact size of a binary digest, but is too small to fit a hexadecimal string or a Base64 string. 您的malloc(20 * sizeof(unsigned char))具有二进制摘要的确切大小,但是太小而不适合十六进制字符串或Base64字符串。 I guess that the unsigned char * points to a binary digest. 我想unsigned char *指向二进制摘要。

But the char * came from the command-line arguments of main() , so the char * probably points to a string. char *来自main()的命令行参数,因此char *可能指向一个字符串。 Command-line arguments are always C strings; 命令行参数始终是C字符串; they end with the NUL terminator '\\0' and never contain '\\0' in the string. 它们以NUL终止符'\\0'结尾,并且从不在字符串中包含'\\0' Raw binary digests might contain '\\0' , so they don't work as command-line arguments. 原始二进制摘要可能包含'\\0' ,因此它们不能用作命令行参数。

The code to convert a SHA-1 digest from hexadecimal string to raw binary might look like 将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;
}

Don't use strncpy(dst, src, 20) to copy raw binary digests. 不要使用strncpy(dst, src, 20)来复制原始二进制摘要。 The strncpy(3) function stops copying if it finds a '\\0' ; strncpy(3)函数如果找到'\\0'则停止复制; so if your digest contains '\\0' , you lose part of the digest. 因此,如果您的摘要包含'\\0' ,则会丢失部分摘要。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM