Ignore the first part (at least!) of the first answer you got. There are some pretty decent programmers that answer questions around here in C++, C, Java, Javascript and VB, plus some folks that know Python, Assembler, Scheme, Perl, Ruby or other lesser-used tongues.
This compiled just fine with GCC, after I added a # to "#include". I'm surprised the C++ guru didn't catch that on the first bounce. It compiles with Visual C++ too, but turning on max warning levels points out two things that you want to change.
1. Make that "int main" or "int main(void)" instead of just "main()". The K&R style of function header has been deprecated for about 20 years now. A function needs a return type, and the return type for the main function must be int.
2. You define the layout of the (struct yy) type inside the definition of the (struct xx) type. That's not illegal, but it's more complicated than it needs to be. It's better to separate those as two different top-level declarations:
struct xx /* This is an xx object */
{
int x; /* An xx object contains an int */
struct yy *q; /* ...and points to a yy object */
};
struct yy /* This is a yy object */
{
char s; /* A yy object contains a char */
struct xx *p; /* ...and points to an xx object */
};
There's no advantage to having yy defined inside xx. The only time I'd recommend including a struct definition within another struct is when that inner struct occurs (as an object, not a pointer) inside the outer struct, and ONLY occurs there.
Edit: I just looked at my test program and added a few statement to test things out, and found out that the nested version exposes a bug in Visual C/C++ 2008 and 2010. At least, I think it's a bug. It treats the nested declaration of yy with xx as the declaration of an unnamed variable. As a result, the xx struct is bigger than it ought to be. GNU C works as expected, but it warns (reasonably) about declaration that doesn't declare anything.
This is yet another reason for separate declarations. Do things in a weird way, and you're more likely to run into less-tested areas of compiler behavior.