Is this Undefined Behaviour?
Yes.
C doesn't officially have the one dentition rule like C++ and this post says multiple definitions are ok? Are different translation units allowed to define structures with the same name?
C does not have the exactly the same one-definition rule that C++ has, but it does have similar rules. There can be at most one external definition of each identifier with external linkage anywhere in the program. There can be at most one definition of an identifier with internal linkage in any given translation unit. There can be at most one definition of an identifier with no linkage in the same namespace within the scope of that identifier, except that typedefs may be redefined identically.
The answer you referred to explains that because structure type declarations have no linkage, you can re-use structure tags in different translation units, but that is not sufficient for the needs of the code presented in this question.
Here, in order for the behavior of the program to be well defined, all declarations of function get()
anywhere within must be compatible with each other (C17, 6.2.7/2). Declarations include definitions, so that means that the type specified by get()
in its prototype in 0.c
must be compatible with its definition in 1.c
. "Compatible" is a defined term in C, covered by section 6.2.7 of the language specification, including several others by reference.
The rules for function declarations are in paragraph 6.7.6.3/15. The most relevant provision is the very first sentence:
For two function types to be compatible, both shall specify compatible return types.
We go back to 6.2.7/1 for the definition of structure type compatibility:
two structure, union, or enumerated types declared in separate
translation units are compatible if their tags and members satisfy the
following requirements: If one is declared with a tag, the other shall
be declared with the same tag. If both are completed anywhere within
their respective translation units, then the following additional
requirements apply: there shall be a one-to-one correspondence between
their members such that each pair of corresponding members are
declared with compatible types; [...] and if one member of the pair is
declared with a name, the other is declared with the same name. For
two structures, corresponding members shall be declared in the same
order.
Your two struct test
types are (perforce) defined with the same tag, and their members have the same names in the same order, but their corresponding members do not have compatible types (details left as an exercise). As a result, the declaration of function get()
in 0.c
is not compatible with the definition in 1.c
, and therefore the program has undefined behavior -- and still would even if get()
were never called.