I can do this:
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
But what's the right way to get a hexadecimal number into the program via the command line?
unsigned char cTest = argv[1];
doesn't do the trick. That produces a initialization makes integer from pointer without a cast warning.
As the type of main
indicates, arguments from the command line are strings and will require conversion to different representations.
Converting a single hexadecimal command-line argument to decimal looks like
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("%ld\n", strtol(argv[1], NULL, 16));
return 0;
}
Example usage:
$ ./hex ff
255
Using strtol
and changing the final argument from 16 to 0 as in
printf("%ld\n", strtol(argv[1], NULL, 0));
makes the program accept decimal, hexadecimal (indicated by leading 0x
, and octal (indicated by leading 0
) values:
$ ./num 0x70
112
$ ./num 070
56
$ ./num 70
70
Using the bash command shell, take advantage of ANSI-C Quoting to have the shell perform the conversion, and then your program just prints the values from the command line.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
unsigned char value = argv[i][0];
if (strlen(argv[i]) > 1)
fprintf(stderr, "%s: '%s' is longer than one byte\n", argv[0], argv[i]);
printf(i + 1 < argc ? "%u " : "%u\n", value);
}
return 0;
}
Bash supports many formats of the form $'...'
, but $'\xHH'
appears to be the closest match to your question. For example:
$ ./print-byte $'\xFF' $'\x20' $'\x32'
255 32 50
Maybe you pack the values from the command line into a string and print it.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
if (argc > 1) {
char *s = malloc(argc);
if (!s) {
fprintf(stderr, "%s: malloc: %s\n", argv[0], strerror(errno));
return 1;
}
for (i = 1; i < argc; i++)
s[i - 1] = strtol(argv[i], NULL, 16) & 0xff;
s[argc - 1] = '\0';
printf("%s\n", s);
free(s);
}
return 0;
}
In action:
$ ./pack-string 48 65 6c 6c 6f 21
Hello!
All of the above is reinventing wheels that bash and the operating system already provide for you.
$ echo $'\x48\x65\x6c\x6c\x6f\x21'
Hello!
The echo
program prints its command-line arguments on the standard output, which you can think of as a for
loop over the arguments and a printf
for each.
If you have another program that performs the decoding for you, use Command Substitution that replaces a command surrounded by backticks or $()
with its output. See examples below, which again use echo
as a placeholder.
$ echo $(perl -e 'print "\x50\x65\x72\x6c"')
Perl
$ echo `python -c 'print "\x50\x79\x74\x68\x6f\x6e"'`
Python