C++03 standard 1.8 The C+ + object model:
Relevant parts of §1: An object is a region of storage... Some objects are polymorphic... For other objects, the interpretation of the values found therein is determined by the type of the expressions used to access them."
In your example, a
is an object with automatic storage duration that is deallocated when the execution leaves the scope. Basically, memory where it resides is available to you and you can store whatever you want there:
int i;
char* myStr = reinterpret_cast<char*>(&i);
myStr[0] = 'H';
myStr[1] = 'i';
myStr[2] = '!';
myStr[3] = '\0';
std::cout << myStr;
(Full example is here)
What you should consider here is the lifetime of object that you "abuse" in this way, i.e. if you still keep the pointer to this memory even after the object has been deallocated, accessing this memory will lead to undefined behaviour.
Just note that just because the language allows you to do something, it doesn't mean you should do it. Use features of this language the way they were meant to be used. After all, you are not writing codes just so that "it works".
And to your question about the size of empty class, same part of the standard also says:
§4: If a complete object, a data member (9.2), or an array element is of class type, its type is considered the most derived class, to distinguish it from the class type of any base class subobject; an object of a most derived class type is called a most derived object.
§5: Unless it is a bit-field (9.6), a most derived object shall have a non-zero size and shall occupy one or more bytes of storage. Base class sub-objects may have zero size. An object of POD type (3.9) shall occupy contiguous bytes of storage.
So it is guaranteed by standard that objects of an empty class such as yours will occupy at least 1 byte.