Skip to content

Instantly share code, notes, and snippets.

@JamesNewton
Created February 2, 2018 01:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamesNewton/37b8eec1260d33c97bcb630f5ab1685c to your computer and use it in GitHub Desktop.
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.
//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;
}
@JamesNewton
Copy link
Author

To run the code and see the output go to:
https://ideone.com/HDqleJ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment