What is the type of foo.a? It's definitely not a pointer, because we assign 10 as a value, not address. But it's not a value type as well, because it changes data of foo. In C++ I would just say that it's a reference, but in C?

The only reason a reference is "needed" here in C++ is operator overloading. In C, the = sign is not a function call that needs a reference argument. It's simply an operator. It can't be redefined and made to do nonsensical stuff, so a normal lvalue is perfectly fine for it.

Note that there's no fundamental reason C++ needed references for this either. It could just as well have specified the overloaded operator= etc. functions to receive pointers rather than references.

The type of foo.a is int. Think about it this way: writing foo.a = 5 is the same as writing *((int*)(&foo + offset_of_a)) = 5 - it's just writing data to a certain memory location which is to be interpreted a a value of type int.