Created
February 2, 2018 01:49
-
-
Save JamesNewton/37b8eec1260d33c97bcb630f5ab1685c to your computer and use it in GitHub Desktop.
Options for shortest possible binary to hex, multiple data types, light, fast, easy for the C compiler to optimize.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//For a live version of this, see: | |
//https://ideone.com/HDqleJ | |
#include <stdio.h> | |
#define loctype long | |
//#define loctype short | |
//#define loctype double | |
//#define loctype float | |
#define value 3735928559 //a fun value which turns into DEADBEEF in hex. | |
#define EOL 13 | |
//Normally, of course, you would just printf in hex format: | |
// printf("%04X", value); //replace 04 with sizeof(value) | |
//But printf is ungodly huge and slow. If you need something tiny and faster... | |
char hexnibblea (unsigned char b) { | |
if (b>9) b+=('A'-10); else b+='0'; | |
return b; | |
} | |
/* A good C compiler should generate something like | |
LOAD b | |
SUB #9 | |
LOAD #55 ; 'A'-10 | |
SKIP ABOVEZERO | |
LOAD #48 ; '0' | |
ADD b | |
SAVE b | |
You don't want to know what they really generate. *facepalm* | |
*/ | |
//if you don't mind wasting some program memory: | |
#define hexnibble_m(b) "0123456789ABCDEF"[b] | |
// or if you will use it more than once: | |
char hexnibble (unsigned char b) { | |
return hexnibble_m(b); | |
} | |
void puts_hex_r(loctype h) { //type* & order agnostic, lsb first output | |
char i; | |
for (i = sizeof(loctype)*2-1; i>=0; i--) { //down count is faster | |
putchar(hexnibble((unsigned char)h&0xF)); | |
h/=16; // easily optimized by most compilers | |
} | |
putchar(EOL); | |
} | |
//the only problem with the above is that it is lsb first. If you want msb first... | |
//and you have memory for a buffer: | |
//https://stackoverflow.com/a/36968534/663416 | |
//otherwise... | |
//Note: the following code is horrific. pointers, order dependant, fails for floats. | |
void puts_hex_f(loctype h) { | |
char i; | |
unsigned char n; | |
unsigned char *p = (unsigned char *)&h+sizeof(loctype)-1; | |
for (i = sizeof(loctype)-1; i>=0; i--) { | |
n = p[0]; | |
putchar(hexnibble(n>>4&0xF)); | |
putchar(hexnibble(n&0xF)); | |
p--; | |
} | |
putchar(EOL); | |
} | |
//slightly better is doing a union to join a byte array to the value | |
//Note: the following code is horrific. wastes memory, order dependant, no floats. | |
void puts_hex_f2(loctype h2) { | |
union { | |
loctype val; | |
unsigned char b[sizeof(loctype)]; | |
} h; | |
h.val=h2; | |
char i; | |
for (i=sizeof(loctype)-1;i>=0;i--) { | |
putchar(hexnibble(h.b[i]>>4&0xF)); | |
putchar(hexnibble(h.b[i]&0xF)); | |
} | |
putchar(EOL); | |
} | |
//That isn't bad if you want to show the internal representation of a value... | |
//and again, if you have a buffer, life is grand | |
void puts_hex_b(loctype h) { | |
char buf[sizeof(loctype)*2]; | |
char i; | |
for (i = sizeof(loctype)*2-1; i>=0; i--) { //down count is faster | |
buf[i] = hexnibble((unsigned char)h&0xF); | |
h/=16; // easily optimized by most compilers | |
} | |
puts(buf); | |
} | |
int main(void) { | |
puts_hex_b(value); | |
puts_hex_f2(value); | |
puts_hex_f(value); | |
puts_hex_r(value); | |
printf("%04X", value); | |
putchar(EOL); | |
putchar(hexnibble(0)); | |
putchar(hexnibble(1)); | |
putchar(hexnibble(2)); | |
putchar(hexnibble(3)); | |
putchar(hexnibble(4)); | |
putchar(hexnibble(5)); | |
putchar(hexnibble(6)); | |
putchar(hexnibble(7)); | |
putchar(hexnibble(8)); | |
putchar(hexnibble(9)); | |
putchar(hexnibble(10)); | |
putchar(hexnibble(11)); | |
putchar(hexnibble(12)); | |
putchar(hexnibble(13)); | |
putchar(hexnibble(14)); | |
putchar(hexnibble(15)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To run the code and see the output go to:
https://ideone.com/HDqleJ