简体   繁体   中英

Converting char* to unsigned char*

How do I copy a char* to a unsigned char* correctly in C. Following is my code

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. 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 digest can be best represented using a 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*.

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.

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.

Cast the signedness away in the strncpy() call

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. I think you want malloc(20 * sizeof(unsigned char)) , or, as by definition sizeof (unsigned char) is 1 , malloc(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(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.

There is no one way to convert char * to 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:

  • the raw binary digest as an array of exactly 20 octets
  • the digest as a hexadecimal string, like "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
  • the digest as a Base64 string, like "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. I guess that the unsigned char * points to a binary digest.

But the char * came from the command-line arguments of main() , so the char * probably points to a string. Command-line arguments are always C strings; they end with the NUL terminator '\\0' and never contain '\\0' in the string. Raw binary digests might contain '\\0' , so they don't work as command-line arguments.

The code to convert a SHA-1 digest from hexadecimal string to raw binary might look like

#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. The strncpy(3) function stops copying if it finds a '\\0' ; so if your digest contains '\\0' , you lose part of the digest.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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