The first declaration declares two objects John and Jason of unnamed structure.
The second declaration declares two typedef names John and Jason for an unnamed structure.
The third declaration declares a structure with tag person. Then two objects John and Jason of type struct person are created.
1) The first one creates an unnamed structure. Two instances of that unnamed structure are then declared. The region between the closing brace and the semi-colon is the only declaration context associated with the unnamed structure. After the only declarative region has passed, no more instances of the unnamed structure can be made simply because the compiler needs a type-identifier to create an instance.
2) Initially, the members are declared. After the declaration of all members, the unnamed structure is then assigned an identifier. In this particular case, two structures, "John" and "Jason", are declared. Typically, the region in which "John" and "Jason" are declared is used to declare instances of the structure as stated above. In this case, it's used to introduce type-names.
(3) This creates a structure named "person". Further on, two instances of "person", "John" and "Jason", are declared into the current scope.
The 1st and 2nd are more restrictive than the 3rd because:
1) ...the 1st structure is completely unknown. It cannot have constructors, destructors, operators and member functions (in C++).
2) ... the 2nd structure's type-identifier isn't known until the closing-brace of the structure. Therefore, in C++, constructors, destructors, operators and member functions are not allowed.
divine fallacy wrote:
"In the case of (1), when would an unnamed structure be desireable?"
There aren't many uses but they can be used to a group local data in local scopes. For example: