Due to the macro distribution rules in C. Using the str(s)one you defined is fooimmediately placed as #foo, rather than evaluates, the value foo. When you complete it with help xstr, it provides an opportunity to actually evaluate foobefore applying the structure.
The process looks something like this:
str(foo)->#foo->"foo"
xstr(foo)->str(4)->#4->"4"