How to create a hex dump from binary data in C++
http://stahlworks.com/dev/index.php?tool=csc01
How to create a hex dump from binary data in C++ with a few lines of code:
free source code examples for instant use in any project, for windows and linux.
starting point: let's say we have a simple program like this:
#include <stdio.h> int main(int argc, char *argv[]) { char abStack[100]; printf("hello world, abStack == %p\n", abStack); }
and we want to see the binary contents of abStack in a well-formatted hex dump.
solution 1: triple-column hex dump with ASCII representation
#include <stdio.h> #include <ctype.h> void hexdump(void *pAddressIn, long lSize) { char szBuf[100]; long lIndent = 1; long lOutLen, lIndex, lIndex2, lOutLen2; long lRelPos; struct { char *pData; unsigned long lSize; } buf; unsigned char *pTmp,ucTmp; unsigned char *pAddress = (unsigned char *)pAddressIn; buf.pData = (char *)pAddress; buf.lSize = lSize; while (buf.lSize > 0) { pTmp = (unsigned char *)buf.pData; lOutLen = (int)buf.lSize; if (lOutLen > 16) lOutLen = 16; // create a 64-character formatted output line: sprintf(szBuf, " > " " " " %08lX", pTmp-pAddress); lOutLen2 = lOutLen; for(lIndex = 1+lIndent, lIndex2 = 53-15+lIndent, lRelPos = 0; lOutLen2; lOutLen2--, lIndex += 2, lIndex2++ ) { ucTmp = *pTmp++; sprintf(szBuf + lIndex, "%02X ", (unsigned short)ucTmp); if(!isprint(ucTmp)) ucTmp = '.'; // nonprintable char szBuf[lIndex2] = ucTmp; if (!(++lRelPos & 3)) // extra blank after 4 bytes { lIndex++; szBuf[lIndex+2] = ' '; } } if (!(lRelPos & 3)) lIndex--; szBuf[lIndex ] = '<'; szBuf[lIndex+1] = ' '; printf("%s\n", szBuf); buf.pData += lOutLen; buf.lSize -= lOutLen; } } int main(int argc, char *argv[]) { char abStack[100]; printf("hello world, dump of abStack follows:\n"); hexdump(abStack, 100); }
example output:
hello world, dump of abStack follows: >08080000 00000000 00003200 88000000< ..........2..... 00000000 >08080000 781B3200 00003200 8CFC1200< ....x.2...2..... 00000010 >90FC1200 B0FF1200 F088F977 94BEF477< ...........w...w 00000020 >9161E577 D0FE1200 B8FE1200 999E3600< .a.w..........6. 00000030 >00000000 E0FE1200 1B504000 D0FE1200< .........P@..... 00000040 >04904000 27B243B6 03000000 A6D26C36< ..@.'.C.......l6 00000050 >CA00C701< .... 00000060
the above hexdump() function provides
- the raw binary data as hex values, in groups of 4 bytes, with 16 bytes per line
- an ascii representation of the data, where printable
- the hex offset of each record (line)
if you don't want the output on terminal but, for example, into a file-based tracing system like mtk, simply change the printf statement within hexdump().
the above example dumps only 16 data bytes per record. if you need something more compact, try this:
solution 2: hex dump with 32 data bytes, 85 chars per output line
#include <stdio.h> #include <ctype.h> void hexdump(void *pAddressIn, long lSize) { char szBuf[100]; long lIndent = 1; long lOutLen, lIndex, lIndex2, lOutLen2; long lRelPos; struct { char *pData; unsigned long lSize; } buf; unsigned char *pTmp,ucTmp; unsigned char *pAddress = (unsigned char *)pAddressIn; buf.pData = (char *)pAddress; buf.lSize = lSize; while (buf.lSize > 0) { pTmp = (unsigned char *)buf.pData; lOutLen = (int)buf.lSize; if (lOutLen > 32) lOutLen = 32; // create a 85-character formatted output line: sprintf(szBuf, " " " " " [%08lX]", pTmp-pAddress); lOutLen2 = lOutLen; for(lIndex = lIndent, lRelPos = 0; lOutLen2; lOutLen2--, lIndex += 2 ) { ucTmp = *pTmp++; sprintf(szBuf + lIndex, "%02X ", (unsigned short)ucTmp); if (!(++lRelPos & 3)) // extra blank after 4 bytes lIndex++; } if (!(lRelPos & 3)) lIndex--; szBuf[lIndex+1] = ' '; printf("%s\n", szBuf); buf.pData += lOutLen; buf.lSize -= lOutLen; } } int main(int argc, char *argv[]) { char abStack[100]; printf("hello world, dump of abStack follows:\n"); hexdump(abStack, 100); }
example output follows (some bytes in the middle have been replaced by "(...)"):
hello world, dump of abStack follows: 08080000 00000000 00003200 (...) 781B3200 00003200 8CFC1200 [00000000] 90FC1200 B0FF1200 F088F977 (...) D0FE1200 B8FE1200 999E3600 [00000020] 00000000 E0FE1200 5B4D4000 (...) 852A9A06 05000000 8C3F15E2 [00000040] CD00C701 (...) [00000060]
the most compact solution uses only 76 characters per output line:
solution 3: hex dump with 32 data bytes, 76 chars per output line
#include <stdio.h> #include <ctype.h> void hexdump(void *pAddressIn, long lSize) { char szBuf[100]; long lIndent = 0; long lOutLen, lIndex, lIndex2, lOutLen2; long lRelPos; struct { char *pData; unsigned long lSize; } buf; unsigned char *pTmp,ucTmp; unsigned char *pAddress = (unsigned char *)pAddressIn; buf.pData = (char *)pAddress; buf.lSize = lSize; while (buf.lSize > 0) { pTmp = (unsigned char *)buf.pData; lOutLen = (int)buf.lSize; if (lOutLen > 32) lOutLen = 32; // create a 76-character formatted output line: sprintf(szBuf, " " " " " [%08lX]", pTmp-pAddress); lOutLen2 = lOutLen; for(lIndex = lIndent, lRelPos = 0; lOutLen2; lOutLen2--, lIndex += 2 ) { ucTmp = *pTmp++; sprintf(szBuf + lIndex, "%02X ", (unsigned short)ucTmp); } szBuf[lIndex+1] = ' '; printf("%s\n", szBuf); buf.pData += lOutLen; buf.lSize -= lOutLen; } } int main(int argc, char *argv[]) { char abStack[100]; printf("hello world, dump of abStack follows:\n"); hexdump(abStack, 100); }
example output follows (some bytes in the middle have been replaced by "(...)"):
080800000000000000003200 (...) 781B3200000032008CFC1200 [00000000] 90FC1200B0FF1200F088F977 (...) D0FE1200B8FE1200999E3600 [00000020] 00000000E0FE12002B4D4000 (...) AE6E71210500000054B6122D [00000040] CE00C701 (...) [00000060]