Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: David Brown Newsgroups: comp.lang.c Subject: Re: do { quit; } else { } Date: Wed, 9 Apr 2025 13:51:55 +0200 Organization: A noiseless patient Spider Lines: 132 Message-ID: References: <8634enhcui.fsf@linuxsc.com> <86ldsdfocs.fsf@linuxsc.com> <20250406161323.00005809@yahoo.com> <86ecy5fjin.fsf@linuxsc.com> <20250406190321.000001dc@yahoo.com> <86plhodtsw.fsf@linuxsc.com> <20250407210248.00006457@yahoo.com> <868qoaeezc.fsf@linuxsc.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Wed, 09 Apr 2025 13:51:58 +0200 (CEST) Injection-Info: dont-email.me; posting-host="39048323a720df50869558e92437b3ec"; logging-data="614360"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/3Asm/8NKv8maD+YocebYoFph78eqiAas=" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Cancel-Lock: sha1:ndVj+xL2cFfMZsEu4uptYB7860M= In-Reply-To: Content-Language: en-GB Bytes: 5035 On 08/04/2025 20:04, bart wrote: > On 08/04/2025 18:32, Tim Rentsch wrote: >> bart writes: >> >>> On 08/04/2025 15:50, David Brown wrote: >>> >>>> On 08/04/2025 13:35, bart wrote: >>>> >>>>> But this need not be the case.  For example this is module A: >>>>> >>>>> -------------------------- >>>>>   #include >>>>> >>>>>   typedef struct point {float a; float b;} Point; >>>>> >>>>>   float dist(Point); >>>>> >>>>>   int main(void) { >>>>>   Point p = {3, 4}; >>>>>   printf("%f\n", dist(p)); >>>>>   } >>>>> -------------------------- >>>>> >>>>> And this is module B that defines 'dist': >>>>> >>>>> >>>>> -------------------------- >>>>>   #include >>>>> >>>>>   typedef float length; >>>>>   typedef struct _tag {length x, y;} vector; >>>>> >>>>>   length dist(vector p) {return sqrt(p.x*p.x + p.y*p.y);} >>>>> -------------------------- >>>>> >>>>> The types involved are somewhat different, but are compatible >>>>> enough for it to work. >>>> >>>> The two types are entirely compatible. >>> >>> Are they? >> >> No, they are not.  The type names 'Point' and 'vector' name two >> distinct types, and those types are not compatible, because >> the two struct tags are different. >> >> Because the two types are not compatible, even just calling the >> function dist() is undefined behavior. > > I get an incompatible error (from the example you snipped) even when I > remove both struct tags. Of course. They are different types. > > I can't use the same struct tag in the same scope as one will clash with > the other. Yes. > But if I have the second in an inner scope, then I again get > the error. Yes. > > It doesn't seem to be anything to do with struct tags. Correct. Every time you declare a struct - when you have "struct {" or "struct X {", you declare a /new/ type that is incompatible with any other type (except for inter-translation unit compatibility). > > Two typedefs for same struct layout appear to create distinct types; > this fails: "typedef" does not create types - it merely creates an alias for an existing type. (Is it a questionable choice of keyword? Yes, it certainly is. So you have to learn what it means.) "struct" declarations (and "union" declarations) create types. > >   typedef struct {float x, y;} Point; This creates a new anonymous type, then declares "Point" to be an alias for it. >   typedef struct {float x, y;} vector; This creates a new anonymous type, then declares "vector" to be an alias for it. "Point" and "vector" thus refer to different types. > >   Point p; >   vector v; > >   p=v; > > > But this works: > >   typedef struct {float x, y;} Point, vector; This creates a new anonymous type, then declares "Point" and "vector" to be aliases of it. They therefore refer to the same type. > >   Point p; >   vector v; > >   p=v; > > So it seems to depend on whether Point and vector share the same > internal descriptor for the struct. > It depends on whether they are declared as aliases for the same type, or for different types. > In my original example, the structs were defined in separate translation > unit, so the compiler has to take things on trust. > Yes - as explained in 6.2.7p1 of the standard. Having them in separate translation units is critical to the difference.