I know in C# you can use String.Format method. But how do you do this in C++? Is there a function that allows me to convert a byte to a Hex?? Just need to convert a 8 byte long data to Hex, how do I do that?
-
sprintf() ? fillerfillerfiller – Martin James May 15 '12 at 10:48
-
@arrowdodger Sorry, yes I want it hexademical – Danny May 15 '12 at 10:49
10 Answers
If you want to use C++ streams rather than C functions, you can do the following:
int ar[] = { 20, 30, 40, 50, 60, 70, 80, 90 };
const int siz_ar = sizeof(ar) / sizeof(int);
for (int i = 0; i < siz_ar; ++i)
cout << ar[i] << " ";
cout << endl;
for (int i = 0; i < siz_ar; ++i)
cout << hex << setfill('0') << setw(2) << ar[i] << " ";
cout << endl;
Very simple.
Output:
20 30 40 50 60 70 80 90
14 1e 28 32 3c 46 50 5a

- 379,657
- 97
- 704
- 746

- 10,247
- 7
- 47
- 64
-
59Worth noting that you should `#include
` and that `hex`, `setfill` and `setw` are all in the `std` namespace. Further `hex` is persistent, so you can pull it outside the loop, and you should call `dec` when you're done so that the stream prints future integral values in decimal, assuming that's what you want. – Drew Noakes Aug 30 '14 at 21:29 -
3Very good answer --- it could use some examples what ``hex`` and ``setfill`` are. – jb. Nov 21 '14 at 20:58
-
8To expound upon @Andrew, if you have a char c and want to print values > 0x80 as hex, you need to cast it as (unsigned int)(unsigned char)c. Otherwise you'll print the 32-bit 2's complement. – jtbr Jun 27 '17 at 21:08
-
@DrewNoakes I have attempted to cover those points at: https://stackoverflow.com/a/53673624/895245 – Ciro Santilli OurBigBook.com Dec 07 '18 at 16:43
-
3@jbr `unsigned char` doesn't work. For newcomers, if you have `char a = 20; cout << hex << a << endl;`, it will give you garbage. Because "`char` has a special overload for ostream with `operator<<`". So you need to cast to e.g. `int`, like `cout << hex << (int)a << endl;`. As for print values > `0x80` as hex, a casting is also required. The reason is [printing hexadecimal characters in c](https://stackoverflow.com/questions/8060170/printing-hexadecimal-characters-in-c). – Rick Nov 21 '19 at 16:12
-
Just noticed this is likely not what OP wanted. What OP wants for that array is likely `00 00 00 20 00 00 00 30`. – Ciro Santilli OurBigBook.com Aug 16 '20 at 05:41
Well you can convert one byte (unsigned char) at a time into a array like so
char buffer [17];
buffer[16] = 0;
for(j = 0; j < 8; j++)
sprintf(&buffer[2*j], "%02X", data[j]);

- 15,967
- 6
- 64
- 112

- 1,226
- 15
- 19
-
I assumed he wanted to convert a array of numbers into a array of hex numbers, i guess he probably wanted a hex string – bentech May 15 '12 at 10:56
-
9I would note that this is actualy C-way, not C++. I'd rather accept @Component 10 answer. – arrowd May 15 '12 at 14:24
-
3If the char in question is negative, the variadic function's type promotion will cause six leading "F"s. – geometrian Jun 05 '13 at 08:46
-
1
-
@imallett yes, definitely it should use `%hhx` or `unsigned char`. For newcomers: [printing hexadecimal characters in c](https://stackoverflow.com/questions/8060170/printing-hexadecimal-characters-in-c) – Rick Nov 21 '19 at 15:46
-
C:
static void print_buf(const char *title, const unsigned char *buf, size_t buf_len)
{
size_t i = 0;
fprintf(stdout, "%s\n", title);
for(i = 0; i < buf_len; ++i)
fprintf(stdout, "%02X%s", buf[i],
( i + 1 ) % 16 == 0 ? "\r\n" : " " );
}
C++:
void print_bytes(std::ostream& out, const char *title, const unsigned char *data, size_t dataLen, bool format = true) {
out << title << std::endl;
out << std::setfill('0');
for(size_t i = 0; i < dataLen; ++i) {
out << std::hex << std::setw(2) << (int)data[i];
if (format) {
out << (((i + 1) % 16 == 0) ? "\n" : " ");
}
}
out << std::endl;
}

- 464
- 4
- 6
You can do it with C++20 std::format
which is similar to String.Format
in C#:
std::string s = std::format("{:x}", std::byte(42)); // s == 2a
Until std::format
is widely available you can use the {fmt} library, std::format
is based on (godbolt):
std::string s = fmt::format("{:x}", std::byte(42)); // s == 2a
Disclaimer: I'm the author of {fmt} and C++20 std::format
.

- 49,672
- 25
- 199
- 336
-
1awesome library... ! sorry to say this doesn't work for me. Your godbolt link says so, and so does my local compiler with fresh checkout of fmt from github – Oliver Schönrock Mar 02 '22 at 01:33
-
seems to be a regression on trunk. 8.1.1 works fine. godbolt is on trunk and doesn't have 8.1.1 available. Same results on gcc-11 and clang-13. – Oliver Schönrock Mar 02 '22 at 08:00
-
-
1
-
1I don't think `std::format` supports `std::byte`. It should, and `{fmt}` does, but the enum stuff you have in `{fmt}` isn't in `std`. – Barry Apr 30 '23 at 19:09
Printing arbitrary structures in modern C++
All answers so far only tell you how to print an array of integers, but we can also print any arbitrary structure, given that we know its size. The example below creates such structure and iterates a pointer through its bytes, printing them to the output:
#include <iostream>
#include <iomanip>
#include <cstring>
using std::cout;
using std::endl;
using std::hex;
using std::setfill;
using std::setw;
using u64 = unsigned long long;
using u16 = unsigned short;
using f64 = double;
struct Header {
u16 version;
u16 msgSize;
};
struct Example {
Header header;
u64 someId;
u64 anotherId;
bool isFoo;
bool isBar;
f64 floatingPointValue;
};
int main () {
Example example;
// fill with zeros so padding regions don't contain garbage
memset(&example, 0, sizeof(Example));
example.header.version = 5;
example.header.msgSize = sizeof(Example) - sizeof(Header);
example.someId = 0x1234;
example.anotherId = 0x5678;
example.isFoo = true;
example.isBar = true;
example.floatingPointValue = 1.1;
cout << hex << setfill('0'); // needs to be set only once
auto *ptr = reinterpret_cast<unsigned char *>(&example);
for (int i = 0; i < sizeof(Example); i++, ptr++) {
if (i % sizeof(u64) == 0) {
cout << endl;
}
cout << setw(2) << static_cast<unsigned>(*ptr) << " ";
}
return 0;
}
And here's the output:
05 00 24 00 00 00 00 00
34 12 00 00 00 00 00 00
78 56 00 00 00 00 00 00
01 01 00 00 00 00 00 00
9a 99 99 99 99 99 f1 3f
Notice this example also illustrates memory alignment working. We see version
occupying 2 bytes (05 00
), followed by msgSize
with 2 more bytes (24 00
) and then 4 bytes of padding, after which comes someId
(34 12 00 00 00 00 00 00
) and anotherId
(78 56 00 00 00 00 00 00
). Then isFoo
, which occupies 1 byte (01
) and isBar
, another byte (01
), followed by 6 bytes of padding, finally ending with the IEEE 754 standard representation of the double field floatingPointValue
.
Also notice that all values are represented as little endian (least significant bytes come first), since this was compiled and run on an Intel platform.

- 19,015
- 11
- 82
- 104
This is a modified version of the Nibble to Hex method
void hexArrayToStr(unsigned char* info, unsigned int infoLength, char **buffer) {
const char* pszNibbleToHex = {"0123456789ABCDEF"};
int nNibble, i;
if (infoLength > 0) {
if (info != NULL) {
*buffer = (char *) malloc((infoLength * 2) + 1);
buffer[0][(infoLength * 2)] = 0;
for (i = 0; i < infoLength; i++) {
nNibble = info[i] >> 4;
buffer[0][2 * i] = pszNibbleToHex[nNibble];
nNibble = info[i] & 0x0F;
buffer[0][2 * i + 1] = pszNibbleToHex[nNibble];
}
} else {
*buffer = NULL;
}
} else {
*buffer = NULL;
}
}

- 72,589
- 19
- 149
- 183

- 49
- 1
I don't know of a better way than:
unsigned char byData[xxx];
int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
sprintf(pBuffer[2 * i], "%02X", byData[i]);
}
You can speed it up by using a Nibble to Hex method
unsigned char byData[xxx];
const char szNibbleToHex = { "0123456789ABCDEF" };
int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
// divide by 16
int nNibble = byData[i] >> 4;
pBuffer[2 * i] = pszNibbleToHex[nNibble];
nNibble = byData[i] & 0x0F;
pBuffer[2 * i + 1] = pszNibbleToHex[nNibble];
}

- 4,855
- 1
- 26
- 31

- 31
- 1
-
Use of `sprintf()` is generally considered dangerous for good reason. Here, the usage is ok since you carefully allocate enough space, but in general, I would avoid it. I like the nibble approach much better. – cmaster - reinstate monica Aug 02 '13 at 22:15
-
-
Yet another answer, in case the byte array is defined as char[]
, uppercase and separated by spaces.
void debugArray(const unsigned char* data, size_t len) {
std::ios_base::fmtflags f( std::cout.flags() );
for (size_t i = 0; i < len; ++i)
std::cout << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (((int)data[i]) & 0xFF) << " ";
std::cout << std::endl;
std::cout.flags( f );
}
Example:
unsigned char test[]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
debugArray(test, sizeof(test));
Output:
01 02 03 04 05 06

- 115
- 7
Use C++ streams and restore state afterwards
This is a variation of How do I print bytes as hexadecimal? but:
- runnable
- considering that this alters the state of cout and trying to restore it at the end as asked at: Restore the state of std::cout after manipulating it
main.cpp
#include <iomanip>
#include <iostream>
int main() {
int array[] = {0, 0x8, 0x10, 0x18};
constexpr size_t size = sizeof(array) / sizeof(array[0]);
// Sanity check decimal print.
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
// Hex print and restore default afterwards.
std::ios cout_state(nullptr);
cout_state.copyfmt(std::cout);
std::cout << std::hex << std::setfill('0') << std::setw(2);
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
std::cout.copyfmt(cout_state);
// Check that cout state was restored.
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
}
Compile and run:
g++ -o main.out -std=c++11 main.cpp
./main.out
Output:
0 8 16 24
00 8 10 18
0 8 16 24
Tested on Ubuntu 16.04, GCC 6.4.0.

- 347,512
- 102
- 1,199
- 985
-
This is not thread-safe. That may or may not matter, depending on the use case. However I think it at least bears mentioning. – Lightness Races in Orbit Dec 07 '18 at 17:00
-
Oh, and it's not exception-safe either. That's why the page you link to has [better alternatives](https://stackoverflow.com/a/2273351/560648) ;) – Lightness Races in Orbit Dec 07 '18 at 17:02
Another C++17 alternative because why not!
std::cout<<std::hex<<std::setfill('0');
struct {
std::uint16_t first{666};
std::array<char,4> second{'a','b','c','d'};
} my_struct;
auto ptr = reinterpret_cast<std::byte*>(&my_struct);
auto buffer = std::vector<std::byte>(ptr, ptr + sizeof(my_struct));
std::for_each(std::begin(buffer),std::end(buffer),[](auto byte){
std::cout<<std::setw(2)<<std::to_integer<int>(byte)<<' ';
});
Executable code here.

- 533
- 1
- 5
- 14