Deutsch English Français Italiano |
<vtammh$174ev$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: Fri, 11 Apr 2025 11:17:04 +0200 Organization: A noiseless patient Spider Lines: 136 Message-ID: <vtammh$174ev$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> <vt5fed$ccri$1@dont-email.me> <vt5js2$g1t7$1@dont-email.me> <20250409142303.00004645@yahoo.com> <87ikndqabc.fsf@nosuchdomain.example.com> <20250410115501.000037a5@yahoo.com> <vt8ei8$2vn84$1@dont-email.me> <20250410080629.532@kylheku.com> <vt94q5$3jjod$1@dont-email.me> <vt9628$3hhr8$3@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Fri, 11 Apr 2025 11:17:06 +0200 (CEST) Injection-Info: dont-email.me; posting-host="414a89bbcf5f663aa3944451ac130353"; logging-data="1282527"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18s/2hrKJFHoPf9KOFL2ALnwREn8syQoaY=" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Cancel-Lock: sha1:0omsfWKLAqVb8Mdf/q0xKkkQQA8= In-Reply-To: <vt9628$3hhr8$3@dont-email.me> Content-Language: en-GB Bytes: 7638 On 10/04/2025 21:27, bart wrote: > On 10/04/2025 20:05, David Brown wrote: >> On 10/04/2025 17:41, Kaz Kylheku wrote: >>> On 2025-04-10, David Brown <david.brown@hesbynett.no> wrote: >>>> So currently, I have no explanation for why you may write "static int >>>> foo; extern int foo;" and have "foo" be internal linkage, while "extern >>>> int foo; static int foo;" is not allowed. >>> >>> What's also not allowed is "static int foo; int foo;" ! >>> >>> It's because "extern" means "refer to the existing file scope >>> declaration of the identifer if there is one propagating its >>> properties, including linkage; otherwise if it doesn't exist, >>> create an external linkage reference" >>> >> >> That's a summary of how "extern" works, but it results in a kind of >> circular argument or tautology - it's just saying "extern means what >> it means". It does not explain /why/ it works this way, or where the >> rules came from, why C has use of a single keyword that works this >> way, and why it is called "extern". >> >> It would be much simpler if we had "static int x;" to mean "declare x >> with internal linkage and define it", "extern int x;" to mean "declare >> x to have extern linkage", and "int x;" to mean "declare x with >> external linkage and define it". That is how you use these in most >> circumstances (and there are gcc warning flags to enforce it, for >> those that want to do that). > > It can't be that simple in C because of shared headers. > > If module A wants to export 'abc' to other modules, then the source code > seen by the compiler for A.c has to look like this: > > extern int abc; // in A.h > ...... > int abc; // in A.c > Yes. In A.c, "abc" is declared to have external linkage, then it is declared with external linkage and defined. > > The other modules include A.h and see 'extern int abc' which means 'abc' > is imported. There is no "import" or "export" in C - only "internal linkage" or "external linkage" - file local or program global, if you prefer. The combinations "declare with external linkage but do not define" and "declare with external linkage and define" are used to achieve import and export of identifiers. > But its home module sees both of these, including the > 'extern' version, but here 'abc' is exported! Yes - "extern" does /not/ mean "export". > > That is counter-intuitive: how can a module both import a name (via > 'extern int') and export it (via 'int' without 'static')? If the keyword "extern" were written "export", I'd agree on it being counter-intuitive. But it is not written that way. The point of "extern" is that it indicates external linkage - program-wide sharing of the identifier in question. It is shared amongst the units that exports it (by defining it) and units that import it (by using it), usually achieved by having the same shared header included by the exporting unit and the importing units. This has a huge advantage compared to languages where importing units read some kind of interface import file but the exporting one does not - it is extremely easy in C to ensure that all your shared identifiers match up correctly by keeping all external declarations in shared headers and all definitions in C files. > > You can't say that A.h is only for consumption by other modules, since > it could include stuff that all module including A will need, such as > macros, types and enums. Of course - "A.h" is /not/ only for consumption by other translation units. (Please call them "translation units" or just "C files", not "modules" since we are discussing the C alternatives to code modules found in some other languages.) "A.h" is for consumption in "A.c" as well. This is the normal way of structuring C code. > > So, here C is complicated because the same attribute has to mean > different things depending on whether this is the entity's home module > or not. No, it means /exactly/ the same thing in both situations. "Linkage" is about the /link/, not one side of the link (export or import). "extern" declares external linkage. Some other programming languages make the distinction between import and export. That can work too, if you have enough extra support (such as compiled "interface" files generated from an exporting module). Without that support - such as is the case for most assembly languages - it's very easy to get mixups between what one assembly file "foo.asm" exports and what other modules import from "foo.inc". One way to handle that limitation is a whole collection of messy macros. I've been there, done that, and am glad to have left it behind. > >> >> C rarely makes things more complicated without a good reason. > > C usually makes things more complicated without a good reason! Nope. > > Here's one example, of dozens, of perfectly legal C: > > long unsigned const long const const typedef int A; > int long unsigned const long const const typedef A; > long unsigned const long const typedef int A; > ..... > That is not more complicated, nor is it without good reason. The language quite simply doesn't bother insisting on a specific order for some parts of declarations. It is simpler to describe in the standard. (Putting storage-class specifiers other than at the start of a declaration has been obsolescent since at least C99 - but it has not been removed from the language. I think that is because it would be extra work in specifying the syntax rules, rather than because many people write declarations like yours.) Nothing will ever stop some programmers from writing complicated or messy code.