How to retrieve the data type of a variable?

In a typical C++ program, you would use the typeid operator, like this:

std::cout << typeid(myVar).name();

However, that requires a compiler feature called Runtime Type Information (RTTI). It's disabled in the Arduino IDE, presumably because it tends to increase the runtime memory requirements of the program.

You can get more information about the resource cost here: https://stackoverflow.com/questions/579887/how-expensive-is-rtti

Any fully-featured C++ compiler will definitely support RTTI though. If you want to try using a 3rd party IDE (such as Eclipse with the Arduino plugin) then you could easily enable it. It's probably not worth the hassle just for that though.


Alternative
A higher-performing (but less flexible) solution would be to use a traits class approach. This involves some funky template meta-programming:

// Generic catch-all implementation.
template <typename T_ty> struct TypeInfo { static const char * name; };
template <typename T_ty> const char * TypeInfo<T_ty>::name = "unknown";

// Handy macro to make querying stuff easier.
#define TYPE_NAME(var) TypeInfo< typeof(var) >::name

// Handy macro to make defining stuff easier.
#define MAKE_TYPE_INFO(type)  template <> const char * TypeInfo<type>::name = #type;

// Type-specific implementations.
MAKE_TYPE_INFO( int )
MAKE_TYPE_INFO( float )
MAKE_TYPE_INFO( short )

You can add MAKE_TYPE_INFO(..) lines for any type you want, including the names of custom classes. You could then use it like this:

int myVar = 17;
Serial.println( TYPE_NAME(myVar) );

Anything you don't define using MAKE_TYPE_INFO(..) will show up as "unknown".

That's some fairly advanced stuff in there, so I won't try to explain how it all works here. There are various tutorials on the web though about C++ template programming if you're interested.

EDIT: It's worth noting that the typeof operator isn't standard C++, but is supported by a few compilers, such as GCC. It's basically an older equivalent of decltype, which appears in the C++11 standard.


I use a simple stupid approach...

// serial print variable type
void types(String a) { Serial.println("it's a String"); }
void types(int a) { Serial.println("it's an int"); }
void types(char *a) { Serial.println("it's a char*"); }
void types(float a) { Serial.println("it's a float"); }
void types(bool a) { Serial.println("it's a bool"); }

This is the concept of polymorphism where multiple functions with different parameter types are created but with the same function name. During run time, the function matching the right number of arguments and argument type(s) will get called. Hope this explanation helps.