C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 15:
[15.22] How can I print a char as a number? How can I print a char* so the output shows the pointer's numeric value? Updated!

Cast it.

C++ streams do what most programmers expect when printing a char. If you print a character, it prints as the actual character, not the numeric value of the character:

#include <iostream>
#include <string>

void f()
{
  char c = 'x';
  std::string s = "Now is";
  char const* t = "the time";
  std::cout << c;     prints a character, in this case, x
  std::cout << 'y';   prints a character, in this case, y
  std::cout << s[2];  prints a character, in this case, w
  std::cout << t[2];  prints a character, in this case, e
}
C++ streams also do the right thing when printing a char*: it prints the string, which must be terminated by '\0'.
#include <iostream>
#include <string>

void f()
{
  char const* s = "xyz";
  std::cout << s;      prints the string, in this case, xyz
  std::cout << "pqr";  prints the string, in this case, pqr
}
These seem obvious only because they are intuitive, but in fact there is some pretty wonderful functionality going on in there. C++ streams interpret the values of your chars into actual human readable symbols according to your current locale, plus they know that if you give them a character-pointer, you probably meant to print the C-like string. The only problem is when you do not want the code to behave this way.

Imagine you have a structure that stores peoples' age as an unsigned char. If you wanted to print that structure, it would not make much sense to say that a person's is 'A'. Or if for some reason you wanted to print the address of that age variable, the stream would start at that address and would interpret every subsequent byte (bytes of your struct or class or even of the stack!) as a character, stopping finally when it reaches the first byte containing '\0'.

//Variable 'age' stores the person's age
unsigned char age = 65;

//Our goal here is to print the person's age:
std::cout << age;    Whoops! Prints 'A', not the numeric age

//Our next goal is to print the age variable's location, that is, its address:
std::cout << &age;   Whoops! Prints garbage, and might crash
This is not what was desired. The simplest, and usually recommended, solution is to cast the char or char* to a type your compiler does not interpret as characters, respectively an int or a void*:
//Variable 'age' stores the person's age
unsigned char age = 65;

//Our goal here is to print the person's age:
std::cout << static_cast<unsigned>(age);       Good: prints 65

//Our next goal is to print the age variable's location, that is, its address:
std::cout << static_cast<void const*>(&age);   Good: prints the variable's address
That works great for explicitly specified types, such as unsigned char shown above. But if you are creating a template, where the type unsigned char above is simply known as some numeric type T, you don't want to assume the proper numeric type is unsigned or anything else. In this case, you want to convert your T object to the proper numeric type, whatever that is.

For example, your type T might be anything from char to int to long or long long (if your compiler supports that already). Or your type T might even be an abstract numeric class that does not even provide a cast to any built-in integer (think safe_integer, ranged_integer or big_num classes, for example).

One way to handle this is through traits or template specialization, but there is a much simpler solution that works for char types without jeopardizing these other types. So long as type T provides a unary + operator with ordinary semantics[*footnote], which is provided for all built-in numeric types, everything will work fine:

template <typename T>
void my_super_function(T x)
{
  ...
  std::cout << +x << '\n';  //promotes x to a type printable as a number, regardless of type
  ...
}
Works like magic. The worst you have to worry about now is that it might be a bit cryptic to other developers. If you are thinking to yourself, "Self, I should probably create a function called promote_to_printable_integer_type() to make my code self-documenting." Unfortunately, C++ currently lacks Type Inference, so writing such a function would require code so complex it would probably bring more bugs than the (potential) ones you would prevent. So short term, the best solution is to just bite the bullet, use operator+ and comment your code.

When your organization gets access to C++11, you can start enjoying the convenience of type inference:

template <typename T>
auto promote_to_printable_integer_type(T i) -> decltype(+i)
{
  return +i;
}
Without going into detail, the return type is "the same type as the type of +i". It might look weird, but like most generic templates, what counts is the ease of use, not the beauty of the template definition itself. Here is a sample use:
void f()
{
  unsigned char age = 65;
  std::cout << promote_to_printable_integer_type(age);   prints 65
}

template <typename T>
void g(T x)
{
  ...
  std::cout << promote_to_printable_integer_type(x);   works for any T that provides unary +
  ...
}
This answer will be updated due to C++11 type inference. Watch this space for updates in the near future!!

[*footnote] If you are defining a class that represents a number, to provide a unary + operator with canonical semantics, create an operator+() that simply returns *this either by value or by reference-to-const.