Liste des Groupes | Revenir à cl c |
On 02/12/2024 10:30, David Brown wrote:Good. (That was not clear to me from your description.)On 01/12/2024 21:12, Bart wrote:Speaking for my scheme, that is exactly what happens.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.
(First, I should say that my programs - sets of source files that will comprise one binary - are organised into 'subprograms', each of which is a chummy collection of modules that effectively import each other. The following is about one subprogram.)That sounds a bit looser than I would like, but I am not sure there is any point in discussing the details here. It is straying way too far from C for this newsgroup.
Only entities marked with 'global' are visble from other modules. But if module X exports names A, B, C, all will be visible from Y.
Further, exported names D, E, F from X will be visible from X. Imports can be circular (but subprograms are hierarchical).
What I object to in other schemes are:I like to keep a /neat/ list of dependencies at the top of files. I usually have a rather good idea of which headers each C and header file requires. In the way I organise my headers, any header file which requires other headers, does so in that header. All my headers have guards to allow safe re-inclusion. So they can be ordered and arranged freely. I also usually have a "common" include file that includes the standard headers that I invariably need (like <stdbool.h>, <stdint.h> and <stddef.h>) along with a selection of definitions, static inline functions, macros, etc., that I use regularly in most projects.
* Where each of dozens of modules contains a ragtag list of imports at the top. These look untidy and need to be endlessly maintained as a fresh imported function is needed from module not yet listed, or an import needs to be deleted as references to it are dropped. (This used to be my scheme too!)
* Where functions are selectively imported from each module. FGS! Instead of a few dozen imports, now there could be hundreds of lines of imported function names to maintain. You'd have time for nothing else!That sounds like you have a very poor organisation of your files. Either you have far too many small files, or you have a few files that are far too big, or you have far too complex connections between your source files. I rarely have more than perhaps a dozen "include" lines in a C or header file. There are exceptions that require more - typically a "main" file that pulls everything together.
I like structured and modular programming. It is strange to me that someone would have the tools for that, and then choose not to use them. But some people seem to prefer piling everything together in one name space.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.Each of my modules creates a namespace. (Also, each of my subprograms creates one namespace for all entities exported from the whole library: that requires 'export' rather than 'global'.
However that namespace is rarely used. If this module imports X which exports function F, then I can write F() instead of X.F().
I only need to use the namespace if:
* This module imports two modules that both export F so there is an ambiguity (this is reported)
* This module has its own F so it shadows any imported versions. This is not reported, but has the issue that, if a local F is freshly created, it can silently shadow the previously imported F().
Indeed - that's why I say it /sounds/ terrible to me. As I said above, I prefer a clear and modular organisation. If I am writing module "foo" and a colleague is writing module "bar" as part of the same program, the last thing we want is automatic import of each other's modules, symbols, functions, etc. - especially not jumbled into the main namespace for the code!>You've never used my scheme.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.
One significant advantage is that because all modules (and subprogram imports) are listed in the lead module (usually that's all it contains), it is very easy to build a different configuration using an alternative lead module with a different collection.
Alternatively, different modules can be commented in or out, in one place. Below is the lead module of my C compiler, what is submitted to my main compiler. No other modules contain any project info (only pcl.m, a separate subprogram/library).
The only thing I haven't yet figured out is how the compiler knows the location of an imported library which may reside elsewhere in the file system. For now this is hardcoded.
Les messages affichés proviennent d'usenet.