Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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*.

like image 601
Rajiv Avatar asked Aug 04 '11 11:08

Rajiv


People also ask

Can I cast a char to unsigned char?

Yes, given your program's semantics, you can safely cast an array of signed chars to a pointer to unsigned char, with which you effectively say, this memory is not an array of signed chars, but an array of unsigned chars.

What is unsigned char * in C?

unsigned char is a character datatype where the variable consumes all the 8 bits of the memory and there is no sign bit (which is there in signed char). So it means that the range of unsigned char data type ranges from 0 to 255.

Is uint8_t always unsigned char?

If it exists, uint8_t must always have the same width as unsigned char . However, it need not be the same type; it may be a distinct extended integer type. It also need not have the same representation as unsigned char ; for instance, the bits could be interpreted in the opposite order.


3 Answers

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.

like image 129
Oliver Charlesworth Avatar answered Sep 20 '22 05:09

Oliver Charlesworth


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.

like image 27
Petr Abdulin Avatar answered Sep 18 '22 05:09

Petr Abdulin


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.

like image 34
pmg Avatar answered Sep 19 '22 05:09

pmg