Warning: mysqli::__construct(): (HY000/1203): User howardkn already has more than 'max_user_connections' active connections in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\includes\artfuncs.php on line 21
Failed to connect to MySQL: (1203) User howardkn already has more than 'max_user_connections' active connections
Warning: mysqli::query(): Couldn't fetch mysqli in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\index.php on line 66
Article <vik28b$390eg$1@dont-email.me>
Deutsch   English   Français   Italiano  
<vik28b$390eg$1@dont-email.me>

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

Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: David Brown <david.brown@hesbynett.no>
Newsgroups: comp.lang.c
Subject: Re: question about linker
Date: Mon, 2 Dec 2024 11:30:35 +0100
Organization: A noiseless patient Spider
Lines: 172
Message-ID: <vik28b$390eg$1@dont-email.me>
References: <vi54e9$3ie0o$1@dont-email.me> <viaqh0$nm7q$1@dont-email.me>
 <877c8nt255.fsf@nosuchdomain.example.com> <viasv4$nm7q$2@dont-email.me>
 <vibr1l$vvjf$1@dont-email.me> <vic73f$1205f$1@dont-email.me>
 <20241129142810.00007920@yahoo.com> <vicfra$13nl4$1@dont-email.me>
 <20241129161517.000010b8@yahoo.com> <vicque$15ium$2@dont-email.me>
 <vid110$16hte$1@dont-email.me> <87mshhsrr0.fsf@nosuchdomain.example.com>
 <vidd2a$18k9j$1@dont-email.me> <8734j9sj0f.fsf@nosuchdomain.example.com>
 <vidnp3$1ovvm$2@paganini.bofh.team> <vihpjh$2hgg1$1@dont-email.me>
 <vihrh1$2hk5l$1@dont-email.me> <vii0jp$2jkd9$1@dont-email.me>
 <viifv8$2opi7$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Mon, 02 Dec 2024 11:30:36 +0100 (CET)
Injection-Info: dont-email.me; posting-host="aa0a75e8a34576a95bb9121ab8c66e54";
	logging-data="3441104"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18XQPHcjVuYZ8l/eMfjbd9Y4s+azmNJt2M="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
 Thunderbird/102.11.0
Cancel-Lock: sha1:wdByOVzUKvXhYJNVdDS3DfJE+wg=
In-Reply-To: <viifv8$2opi7$1@dont-email.me>
Content-Language: en-GB

On 01/12/2024 21:12, Bart wrote:
> On 01/12/2024 15:50, David Brown wrote:
>> On 01/12/2024 15:23, Bart wrote:
> 
>>>> Such lists might have been helpful to some people decades ago, when 
>>>> editors were more primitive.  If I need a list of functions in a 
>>>> file (maybe it's someone else's code, or old code of mine), any 
>>>> programmer's editor or IDE will give me it - updated correctly in 
>>>> real-time, and not out of sync.
>>>
>>> Why isn't this a problem for exported/shared functions?
>>>
>>> That is, for all sorts of functions and variables declared in headers 
>>> where there is a declaration in header, and a definition in some 
>>> 'home' module.
>>>
>>
>> What do you mean here?
> 
> You said you didn't want a list of declarations to maintain for static 
> functions within a module.
> 
> But for non-static functions, which are shared via a header, you /need/ 
> such a list to be maintained:

Okay, I understand your point now.  And I can see there is a certain 
similarity between between maintaining the extern function declarations 
in a header, and maintaining a list of static function declarations in 
the C file.  (I refer to "extern function declarations" to distinguish 
them from static declarations - and because I personally like to include 
the optional "extern" keyword.)

But there are many important differences.

The biggest difference is that header files form the public interface 
for the "module".  That will mean documentation (comments), include's 
for any modules that are required for the declarations, type 
declarations, possibly data, macros, etc., as well as extern function 
declarations.  The header is where you put the specification for the 
module - it's not something that changes often, and the choice of 
function declarations is done with care and planing, usually before 
writing any implementations.  And the header with all its contents is 
vital information for both the implementer of the module, and the users.

Static functions, on the other hand, are internal to the implementation 
and can be changed often.  A list of static function declarations gives 
little or no useful information to anyone.

> 
>   prog.h:   int F(int);
> 
> 
>   prog.c:   #include "prog.h"
> 
>             static int G(int a);
> 
>             int F(int a) {return 0;}
> 
>             static int G(int a) {return 0;}
> 
> 
> Here, you object to having to maintain the declaration for G, but you 
> still need to do so for F, and inside a separate file.
> 

I can't speak for how you or anyone else writes code, but my code would 
never look like that in practice.  (Obviously I know what you wrote is a 
quick example, not real code.)  A local static function might have a 
small, simple name - it is of very local scope, so like local variables 
its purpose can be seen clearly from its definition and use.  An 
exported function, on the other hand, will have a good name, properly 
named parameters, carefully chosen parameter types, comments, and a 
position in the header to suit the structure of the code.  Thus "F" and 
"G" are very different in my code.

Obviously I still need to make sure the declarations and definitions 
match up.

> The declaration for F could also get out of sync, but you don't consider 
> that a problem?

It would be a problem if it happened, yes.

Fortunately, most such errors get caught during a build.  A mismatch 
between a function declaration and its definition will be caught 
immediately as a C error.  Warnings from my compiler catch non-static 
function definitions that don't have a matching extern declaration.  And 
if there is an extern declaration for a function but no definition, then 
there will be a link-time error if that function is used by other 
modules.  (But no error or warning if it is not used.)

> 
> And if it isn't because your tools help with this, then they can help 
> with G too.
> 

As I explained earlier, they /can/ help with some sync errors in lists 
of static forward declarations.

And if I wanted to have such lists of static function declarations, then 
it would not be difficult to make a quick utility script that either 
checked such a list, or generated it directly.  That script could then 
be included in the makefile for automation.

But since I don't use such lists, and don't see any benefit in them, I 
haven't bothered writing such a script.  If those who do write such 
lists use some kind of automation to ensure they are correct, then that 
would be great.

>> I certainly consider it a weakness in C that you don't have clear 
>> requirements and limitations for what can be in a header or a C file, 
>> or how things can be mixed and matched.  Keeping code clear and 
>> well-ordered therefore requires discipline and standardised 
>> arrangement of code and declarations.  Different kinds of projects 
>> will have different requirements here, but for my own code I find it 
>> best to be strict that for any C file "file.c", there will be a header 
>> "file.h" which contains "extern" declarations of any exported 
>> functions or data, along with any type declarations needed to support 
>> these.  My tools will warn on any mismatches, such as non-static 
>> functions without a matching "extern" declaration.  They can't catch 
>> everything - the way C is built up, there is no distinction between 
>> external declarations that should be defined in the same module and 
>> ones that are imported from elsewhere.
> 
> Yes, this is why a module scheme (such as the kind I use) is invaluable.
> 

Agreed.  C does not have a real module scheme as such.  But it supports 
getting similar effects - you just have to be disciplined in the way you 
write your headers.  This has the disadvantage of being less consistent 
than, say, Pascal or Modula 2, especially if the programmer is not 
disciplined.  And it has the advantage in flexibility - I have a scheme 
that I like and that works well for the kind of code I work with, but 
other people prefer other schemes.  It's easy to fall into the trap of 
"my way is the right way", especially when you make your own language 
and you are the only user, but there is always a balance to be sought 
between consistency and flexibility.

> In the example above, you'd define both F and G in one place. There is 
> no header and there are no separate declarations.
> 
> If another module wishes to use F, then it imports the whole module that 
> defines F.
> 
> Some schemes can selectively import individual functions, but to me 
> that's pointless micro-managing.
> 

To me, it is absolutely vital that the importing unit can only see the 
identifiers that were explicitly exported.  It is also absolutely vital 
(and this is a critical missing feature for C - and a good reason to 
switch to C++ even if you use no other feature of that language) that 
the imported identifiers be in their own namespace so that they do not 
conflict with identifiers in the importing unit.  If the language 
provides a feature for importing the external identifiers directly into 
the current unit's namespace, then it has to allow selective import of 
identifiers - otherwise all concepts of scalability and modularity go 
out the window.

> In my scheme, it is not even necessary for individual modules to 
> explicitly import each other: a simple list of modules is provided in 
> one place, and they will automatically import each others' exported 
> entities (which include functions, variables, types, enums, structs, 
> named constants, and macros).
> 

That sounds, frankly, utterly terrible for anyone who worked with other 
people.


========== REMAINDER OF ARTICLE TRUNCATED ==========