Deutsch   English   Français   Italiano  
<vt5n0s$inuo$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: David Brown <david.brown@hesbynett.no>
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: <vt5n0s$inuo$1@dont-email.me>
References: <vspbjh$8dvd$1@dont-email.me> <8634enhcui.fsf@linuxsc.com>
 <vsph6b$ce6m$5@dont-email.me> <86ldsdfocs.fsf@linuxsc.com>
 <20250406161323.00005809@yahoo.com> <86ecy5fjin.fsf@linuxsc.com>
 <20250406190321.000001dc@yahoo.com> <86plhodtsw.fsf@linuxsc.com>
 <20250407210248.00006457@yahoo.com> <vt15lq$bjs0$3@dont-email.me>
 <vt2lp6$1qtjd$1@dont-email.me> <vt31m5$2513i$1@dont-email.me>
 <vt3d4g$2djqe$1@dont-email.me> <vt3iqh$2ka99$1@dont-email.me>
 <868qoaeezc.fsf@linuxsc.com> <vt3oeo$2oq3p$1@dont-email.me>
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: <vt3oeo$2oq3p$1@dont-email.me>
Content-Language: en-GB
Bytes: 5035

On 08/04/2025 20:04, bart wrote:
> On 08/04/2025 18:32, Tim Rentsch wrote:
>> bart <bc@freeuk.com> 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 <stdio.h>
>>>>>
>>>>>   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 <math.h>
>>>>>
>>>>>   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.