None of this applies to C++.  In C++ prefer:
struct Foo
{
   . . .
};
The rest only applies to C.
Technically struct Foo {}; is sufficient for most purposes.  However it is a bit verbose to use as struct must be repeated each time type Foo is used.
struct Foo {}
void func( struct Foo* foo );
A typedef makes this simpler.
struct Foo { };
typedef struct Foo Foo;
void func( Foo* foo );
This can be further shortened with:
typedef struct Foo { } Foo;
void func( Foo* foo );
When doing a one liner it's also possible to use this syntax:
typedef struct { } Foo;
void func( Foo* foo );
This is creating an anonymous struct and then giving it the name Foo.  You see this most often with enums.
typedef enum { } Bar;
There is a reason the intial redundant Foo is usually left there.  It is only only way to create a self referencing struct, like a linked list.
typedef struct Node
{
   Node* next;
} Node;
If the initial Node where ommited there would be no way to declare a pointer to the struct.  Technically this is valid as well, but now you have to come up with 2 names, instead of just one.
typedef struct node_
{
   node_* next;
} Node;
So why use:
typedef struct Foo { } Foo;
For uniformity.  This declaration style covers all you bases, so you never have to think about it when declaring a struct.