C 将字符*转换为无符号字符*

C 将字符*转换为无符号字符*,c,char,sha1,unsigned,strcpy,C,Char,Sha1,Unsigned,Strcpy,如何在C中正确地将字符*复制到无符号字符*。下面是我的代码 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: po

如何在C中正确地将字符*复制到无符号字符*。下面是我的代码

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*

您无法正确地复制它,因为类型不同,编译器警告您这一点


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

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

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

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

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

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;
}
#包括
#包括
int main(int argc,字符**argv)
{
无符号字符*摘要;
void*tmp;/*(void*)与(char*)和(unsigned char*)兼容*/
摘要=malloc(20*sizeof*digest);
国际单项体育联合会(摘要){
tmp=摘要;
如果(argc>2)strncpy(tmp,argv[2],20);
免费(摘要);
}否则{
fprintf(stderr,“无内存。\n”);
}
返回0;
}

还要注意,
malloc(20*sizeof(unsigned char*))
可能不是您想要的。我想你想要
malloc(20*sizeof(unsigned char))
,或者,根据定义
sizeof(unsigned char)
1
malloc(20)
。 如果您确实想在调用中使用每个元素的大小,请使用对象本身,如上面的代码所示。

您可以将memcpy用作:

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

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

没有一种方法可以将
char*
转换为
无符号char*
。它们指向数据,您必须知道数据的格式

SHA-1哈希至少有3种不同的格式:

  • 原始二进制摘要作为正好由20个八位字节组成的数组
  • 摘要为十六进制字符串,如“e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4”
  • 摘要作为Base64字符串,如
    “5en6g6mezrot3xkqkdpomy/BfQ=“
  • 您的
    malloc(20*sizeof(unsigned char))
    具有二进制摘要的精确大小,但太小,无法容纳十六进制字符串或Base64字符串。我猜
    无符号字符*
    指向一个二进制摘要

    但是
    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;
    }
    
    #包括
    #包括
    无符号字符*
    sha1_from_hex(字符*hex)
    {
    int i,m,n,八位组;
    无符号字符*摘要;
    摘要=malloc(20);
    如果(!摘要)
    返回NULL;
    对于(i=0;i<20;i++){
    sscanf(十六进制,“%n%2x%n”、&m、&八进制,&n);
    如果(m!=0 | | n!=2)
    走向失败;
    摘要[i]=八位字节;
    十六进制+=2;
    }
    如果(*十六进制)
    走向失败;
    返回摘要;
    失败:
    免费(摘要);
    返回NULL;
    }
    
    不要使用
    strncpy(dst,src,20)
    复制原始二进制摘要。如果发现
    '\0'
    ,函数将停止复制;因此,如果您的摘要包含
    “\0”
    ,您将丢失部分摘要。

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

    是的,这就是问题所在,我如何以更好的方式解决不兼容问题?如果您能告诉我们为什么需要in作为unsigned char,这可能会帮助我们回答这个问题?为了猜测更好的解决方案,您可能应该使用一个结构或联合,而不是一团无符号字符内存。在
    char*
    vs
    unsigned char*
    的情况下,警告(根据标准,编译器应该将其视为错误!)除了标准中的错误外,很少指示任何错误。几乎所有的标准函数都采用
    char*
    ,但处理的数据实际上被视为
    无符号char的数组。请参见
    strcmp
    @R..:你说“被当作
    无符号字符的数组处理”是什么意思?我举了
    strcmp
    为例。它需要根据解释为
    无符号字符的第一个不匹配字节之间的差异进行比较。IMO在这里引入伪变量只是混淆了代码,没有相应的好处。OP显然想要“比强制转换更好的方法”。模糊化的
    (void*)
    变量以另一种方式完成:我将把决定权留给OP(像你一样,@Oli,我认为不是)。哈希摘要通常表示为摘要十六进制值的ASCII表示(例如“
    b6379dab2c…
    ”)。一个
    char
    绝对可以@因此,演员阵容基本上也可以正常工作,不会出现任何问题。((char*)摘要,argv[2],20);罪