16

Issue

I'm getting no output from a simple cout, whereas a printf will always print the number:

std::cout << variableuint8;  // prints nothing
printf("%u", variableuint8); // prints the number

I've never run into this behavior before, and while I have a work around I would like to understand it.

Context:

Yay, pointers. So it may be a little more involved than as stated. Here's the context - I don't think it should matter, by the time cout and printf get the info it's dereferenced to a simple unsigned char. This is probably more information than needed to resolve the issue, but I wanted to be complete on the off chance that it was relevant.

typedef unsigned char   UInt8;
typedef unsigned short  UInt16;

typedef struct{
   UInt8   len;
   // some other definitions. sizeof(DeviceNotification) <= 8
}DeviceNotification;

UInt8 somerandomdata[8];
DeviceNotification * notification;

notification = (DeviceNotification *) somerandomdata;

std::cout << "Len: (" << notification->len << ")\n";
printf("Len: (%u)\n", notification->len);

The random data is initialized elsewhere. For this output, the first byte in the array is 0x08:

Output:

Len: ()
Len: (8)

Environment

  • Development machine:
    • OS X 10.6.8
    • Compiler LLVM 1.7
    • Xcode 3.2.6
  • Test machine:
    • OS X 10.6.8
Anton Korobeynikov
  • 9,074
  • 25
  • 28
Adam Davis
  • 91,931
  • 60
  • 264
  • 330
  • I just wanna ask is the following line defined in C++? ` notification = (DeviceNotification *) somerandomdata;` doesn't this line invoke undefined behavior if the alignment is not the required alignment of `DeviceNotification`? – Khaled Alshaya Nov 09 '11 at 13:48
  • @AraK These are running on x86, which allows unaligned memory accesses. They may be slower, as they may require two reads of the memory bus to get a value that is split across the boundary, but it works just fine. You can perform some experiments to demonstrate this - if you do, let us know if there is a speed difference. – Adam Davis Nov 09 '11 at 13:54
  • Thanks, that is interesting. It would be nice to write such a micro-benchmark. – Khaled Alshaya Nov 09 '11 at 14:07
  • Even on machines that do have strict alignment requirements, these tend to be applied to fundamental types and not structs. In particular, accessing a byte-size member (such as `UInt8 len`) is safe. – MSalters Nov 10 '11 at 12:06

3 Answers3

12

It's printing the char as a character.

#include <iostream>

int main() {
        unsigned char c = 0x41;
        std::cout << c << std::endl;
        return 0;
}

This prints 'A' to the stdout.

Although in that case, your code should print Len: (*), and I did have verified it prints Len: (*).


Edit: Since in character encodings like ASCII or UTF-8 your console is likely using, the character corresponding to 8 (Backspace) is not visible, it will look like it's not printed.

(In some cases it may cause the previous character (the () to disappear because it is a backspace character. In DOS it may show ◘)

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • That's the issue. You are right about my example output being incorrect - I've changed it to demonstrate the problem as I was actually experiencing it. – Adam Davis Nov 09 '11 at 13:40
  • It is not a real point. The example program should print `42` (`*`), but it does not. – eugene_che Nov 09 '11 at 13:40
  • @tyz I made an error in my example - Kenny is correct. I've modified my example with the actual value I was dealing with. Sorry for the confusion. – Adam Davis Nov 09 '11 at 13:44
4

Have you tried to cast it into int, to avoid depending on the char type that is used by the implementation:

std::cout << (int)variableuint8;

Here is an explanation of what is going on: What is an unsigned char?

To get an idea, your implementation is using unsigned char as char. The ASCII code for 0x08 is the backspace control character, and of course it is not a printable character, that is why you don't see an output in the case of std::cout.

Community
  • 1
  • 1
Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
  • [`std::cout << +variableuint8;`](https://stackoverflow.com/a/28414758/995714) would be simpler – phuclv Jun 24 '17 at 06:04
3

Would std::cout << "Len: (" << (unsigned short)notification->len << ")\n"; print the correct value? I guess casting to an integer is what might be looking for.

az4dan
  • 651
  • 2
  • 10
  • 30