Converting char* to unsigned char*
Solution 1
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.
Solution 2
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.
Solution 3
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.
Solution 4
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.
Solution 5
Just put (char*)
in front of it
or (unsigned char*)
Rajiv
Updated on June 09, 2020Comments
-
Rajiv almost 4 years
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*.
-
Rajiv almost 13 yearsYeah, thats the problem, how do I solve the incompatibility in a better way?
-
Oliver Charlesworth almost 13 yearsIMO, introducing a dummy variable here just obfuscates the code, with no corresponding benefit.
-
noelicus almost 13 yearsIf you could tell us why you need in as an unsigned char, that might help us answer? To take a guess at a better solution you maybe should be using a structure or union instead of a blob of unsigned char memory.
-
pmg almost 13 yearsThe OP apparently wants a "better way than a cast". The obfuscated
(void*)
variable accomplishes a different way: I'll leave the decision if it's better to the OP (like you, @Oli, I think it isn't). -
pmg almost 13 yearsYou have no guarantee accessing
argv[2][19]
is allowed. -
pmg almost 13 yearsWith
memcpy
, you first need to check the length ofargv[2]
to avoid accessing elements outside the array. -
pmg almost 13 yearsI'm not sure the
'\0'
is needed indigest
. Anyway, now you need to check thatstrlen(argv[2])
is small enough for the size allocated fordigest
:) -
cyber_raj almost 13 years@pmg hmm...then OP have to synchronize the allocation size for digest with the (strlen (argv[2]) + 1) * sizeof (unsigned char)
-
R.. GitHub STOP HELPING ICE almost 13 yearsIn the case of
char *
vsunsigned char *
, the warning (which, per the standard, the compiler is supposed to treat as an error!) is rarely indicative of any bug except a bug in the standard. Almost all of the standard functions takechar *
but deal with data which is really treated as an array ofunsigned char
. Seestrcmp
. -
Oliver Charlesworth almost 13 years@R..: What do you mean "treated as an array of
unsigned char
"? -
R.. GitHub STOP HELPING ICE almost 13 yearsI gave
strcmp
as an example. It's required to make its comparison based on the difference between the first non-matching bytes interpreted asunsigned char
. -
R.. GitHub STOP HELPING ICE almost 13 yearsThere are also issues with the fact that, on a non-twos-complement implementation where
char
is signed, the value 0 could have two representations, while only the all-bits-0 byte is the null terminator. This means any function that deals with null terminated strings on such an implementation must be dealing with them asunsigned char []
in order to tell the difference. Admittedly, any non-twos-complement implementation where plainchar
is signed would be rather stupid to begin with though... -
quickly_now over 9 yearsOn some strange machines, sizeof(char) may not be 1. eg TMS320C40. Showing my age here.