Why is it invalid for a union type declared in one function to be used in another function?

  • A+
Category:Languages

When I read ISO/IEC 9899:1999 (see:6.5.2.3), I saw an example like this:

The following is not valid fragment (because the union type is not visible within function f):

struct t1 { int m; }; struct t2 { int m; }; int f(struct t1 * p1, struct t2 * p2) {     if (p1->m < 0)         p2->m = -p2->m;     return p1->m; } int g() {     union {         struct t1 s1;         struct t2 s2;     } u;     /* ... */     return f(&u.s1, &u.s2); } 

I found no errors and warnings when I tested.

My question is: Why is this fragment invalid?

 


The example attempts to illustrate the paragraph beforehand1 (emphasis mine):

6.5.2.3 ¶6

One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.

Since f is declared before g, and furthermore the unnamed union type is local to g, there is no questioning the union type isn't visible in f.

The example doesn't show how u is initialized, but assuming the last written to member is u.s2.m, the function has undefined behavior because it inspects p1->m without the common initial sequence guarantee being in effect.

Same goes the other way, if it's u.s1.m that was last written to before the function call, than accessing p2->m is undefined behavior.

Note that f itself is not invalid. It's a perfectly reasonable function definition. The undefined behavior stems from passing into it &u.s1 and &u.s2 as arguments. That is what's causing undefined behavior.


1 - I'm quoting n1570, the C11 standard draft. But the specification should be the same, subject only to moving a paragraph or two up/down.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: