15

I would like to print the following hashed data. How should I do it?

unsigned char hashedChars[32];
SHA256((const unsigned char*)data.c_str(),
       data.length(), 
       hashedChars);
printf("hashedChars: %X\n", hashedChars);  // doesn't seem to work??
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
louis.luo
  • 2,921
  • 4
  • 28
  • 46

3 Answers3

18

The hex format specifier is expecting a single integer value but you're providing instead an array of char. What you need to do is print out the char values individually as hex values.

printf("hashedChars: ");
for (int i = 0; i < 32; i++) {
  printf("%x", hashedChars[i]);
}
printf("\n");

Since you are using C++ though you should consider using cout instead of printf (it's more idiomatic for C++.

cout << "hashedChars: ";
for (int i = 0; i < 32; i++) {
  cout << hex << hashedChars[i];
}
cout << endl;
Aritz
  • 30,971
  • 16
  • 136
  • 217
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 3
    @vidit the user gave the questions in terms of `printf` so I decided to answer that way. They clearly have a bit of confusion as to how `printf` works, and I wanted to clear that up – JaredPar May 04 '12 at 15:14
  • Ok Sir. I was just thinking because he tagged C++ – vidit May 04 '12 at 15:16
  • 6
    `printf` is valid C++ too! There are times when I use it instead of streams. It has its place. – aardvarkk May 04 '12 at 15:18
  • @vidit i went ahead and added the C++ version as well for completeness – JaredPar May 04 '12 at 15:18
  • @aardvarkk- Yes it is, but I thought we should prefer C++ features compared to the ones carried from C – vidit May 04 '12 at 15:27
  • It's more "would" than "should", otherwise it's like saying things like eg.: `sin` and `isspace` should not be used. – Luis Machuca May 04 '12 at 15:57
  • 1
    @JaredPar So.. the `printf` actually worked for me, but `cout` didn't work for me. I am using `xCode` and "hashedChars: " got printed, but not the rest. – louis.luo May 04 '12 at 15:59
  • @Louis_PIG i tried this locally and it's working on my machine. I'm not familiar enough with xCode to diagnose any problems easily. Have you tried printing without the `hex` to see what it does? – JaredPar May 04 '12 at 16:36
  • 3
    You'll want to ensure that 2 digits are output for each `char`, otherwise you'll be missing some zeros from the output. For the printf change the format to `%02X`, not sure how to do it for cout. – Mark Ransom May 04 '12 at 16:57
  • @JaredPar as indicated by @louis.luo , the `cout << hex << ...` does not work for me – Sven Williamson Mar 01 '17 at 15:47
  • 7
    FWIW, had to cast to `unsigned int`, i.e. `hex << (unsigned int)hashedChars[i]` to get it to work for me. – Tomislav Nakic-Alfirevic Aug 09 '17 at 14:07
  • Does %x actually expect the argument to be of type char and not int or something else? If yes, can you point me to the part of the specification that says that? – Niko O Feb 01 '21 at 08:19
4

In C++

#include <iostream>
#include <iomanip>

unsigned char buf0[] = {4, 85, 250, 206};
for (int i = 0;i < sizeof buf0 / sizeof buf0[0]; i++) {
    std::cout << std::setfill('0') 
              << std::setw(2) 
              << std::uppercase 
              << std::hex << (0xFF & buf0[i]) << " ";
}
daparic
  • 3,794
  • 2
  • 36
  • 38
  • Can you please explain the '0xFF & '. – محمد جعفر نعمة Apr 25 '21 at 09:12
  • 1
    While the `0xFF &` is needed to make it work, however, I must admit that it's not the most idiomatic for this case. The `0xFF &` is promoting the `unsigned char` to become an `int` so that it will result to the call of the proper overloaded method of `std::cout <<` which accepts an `int`. You can also do it like, `1 + buf0[i] - 1` and it still works. Or some esoteric means such as `+buf0[i]`. Or simply via the obvious casting `int(buf0[i])`. There is a need to promote the `buf0[i]` to become an `int`. – daparic Apr 26 '21 at 05:32
  • Many thanks. Indeed, after your response, I tried to go deeper into the cout functionality. It seems that the transformation is related to the shift operator not to cout. For more info, please refer to this https://stackoverflow.com/questions/47439616/can-you-bitwise-shift-a-bool-in-c. A shift of bool returns an int. As a matter of proof: bool b = true; bool d = (b << 2); printf(d ? "1\n" : "0\n"); – محمد جعفر نعمة Apr 27 '21 at 04:31
  • Your findings with regards to the `<<` behaving as a shift operator might be true. But in my example here, take note, the `<<` is not a shift-operator. In my example, the `<<` is overloaded by `std::cout`. Therefore, it is no longer a shift-operator. I promoted `buf0` to an `int` so that it will **hit** right to that `overload` which accepts an `int`. Otherwise, it will **hit** to a different overloaded method. – daparic Apr 27 '21 at 06:41
  • you are totally right! I integrated your idea of 'Anding' to my unit test and forgot about your example while commenting. You use no shifts! – محمد جعفر نعمة Apr 27 '21 at 11:00
0

As mentioned in comments, you need to cast your unsigned char to be recognized as an integral (int or unsigned int since you work with positives values), and you need to add some zeros where the value could be printed by 1 character instead of 2 :

cout << "hashedChars: ";
for (int i = 0; i < 32; i++) {
  cout << std::hex << std::setfill('0') 
       << std::setw(2) << static_cast<int>(hashedChars[i]);
}
cout << endl;
kingsjester
  • 94
  • 1
  • 12