So I have a two char array

unsigned char v[2];

I want to show the value of v[0] as a number from 0 to 255 but

cout << v[0] << endl; //prints some garbage

cout << (void*)v[0] << endl; //prints the right thing but in hex

So I tried

cout << (int)v[0] << endl;

or

printf("%d\n", v[0]);

This shows exactly what I wanted but I don't like it at all. Also what I don't understand at all is why this doesn't work:

cout << reinterpret_cast<int>(v[0]) << endl; //compiler error
有帮助吗?

解决方案

(In layman's terms) reinterpret_cast is used to interpret the bits of an object as another type in an implementation-defined manner. You don't want that: you want a conversion (from char to int). Use static_cast instead.

(All possible uses of reinterpret_cast are listed in 5.2.10; this is not one of them.)

其他提示

cout << v[0] << endl; // prints some garbage

Not garbage, but the character that the value in v[0] represents.

cout << (void*)v[0] << endl;

This "converts" the value in v[0] to a pointer (undefined behavior, since it wasn't a pointer to begin with), and prints the value of that pointer as a hex value.

cout << (int)v[0] << endl;

This converts the value in v[0] to an int (well defined; just promote to int) and displays the value.

reinterpret_cast, as others have mentioned, has some constraints on what it can do. The right answer is to use static_cast<int>:

cout << static_cast<int>(v[0]) << endl;
  • reinterpret_cast : "...allows any integral type to be converted into any pointer type and vice versa." Use this only to convert things that could be pointers into the right pointer type (an unsigned char clearly cannot be a pointer in anything other than an 8-bit system).

  • static_cast : Use this when you want to cast a type into another type (like a float to int, or unsigned char to int).

cout tries to print an unsigned char as an ASCII character code, so converting to int via static_cast<int>(v[0]) is the right thing to do.

The way you are using reinterpret_cast, you are trying to read a char as an int, and they are not the same size.

reinterpret_cast converts values of pointer types to other pointer type values or integer values and vice versa, in order to allow a dereference of the destination pointer value. You however try to convert one integer type value to another integer type value. That's not going to work. reinterpret_cast supports the casting of reference types, which is equivalent to the respective pointer value cast with a follow-up dereference. So it appears you wanted to do

// NOTE: THIS IS UNDEFINED BEHAVIOR
cout << reinterpret_cast<int&>(v[0]) << endl; 

This is well-formed, but reinterprets the unsigned char as an integer object, which isn't guaranteed to work (possible issues range from invalid alignment of the storage to incompatible sizes - 1 byte vs 4 bytes). You can solve these cases by doing the (int)v[0] cast, I think that's perfectly fine. You can also say +v[0], which promotes the value to (signed or unsigned) int automatically.

static_cast will, as others have noted, do the right thing. It is weaker than a C-style cast, so it is less likely to be damaging and cause undefined behavior.

reinterpret_cast is also weaker than a C-style cast, but it is not strictly stronger than static_cast; there are things static_cast can do that reinterpret_cast cannot. You have run into one of them.

reinterpret_cast is intended to permit you to take values of one type, store them as values of another, then get back the original type. You can do this to convert beteen integer and pointer types that are compatible. You can use this to convert from one pointer type to another and back again.

In general, a reinterpret_cast converts your to a "holding" value, and that holding value is implementation defined at best, and often using it is undefined behavior.

So you want to avoid using it unless you really really mean it.

Converting a char to an int is not a matter of reinterpreting usually.

static_cast<int>(some_char) will upgrade the char to an int and get you the appropriate value.


However, in certain circumstances I find static_cast too powerful. It can do unsafe pointer conversions, and counts as an explicit conversion.

Both of these can disguise bugs.

You can write a strictly weaker cast as follows:

template<class T, class U>
T implicit_cast( U&& u ) { return std::forward<U>(u); }

now you can

std::cout << implicit_cast<int>(v[0]) << std::endl;

and you get behavior very much like calling a function taking an int with a char argument, which I believe is what you want.


What is going wrong here? Well, std::cout is a stream, and streams pay attention to the type passed. char types are printed as if they are `'a`` style characters, not as if they are small integers.

In order to treat a char as a small integer, you have to convert it to another integer type.

The same is true of char*; they are treated as pointers to null-terminated buffers of char, like "hello world", and not like other pointers.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top