Page 1 of 2
C Header File conventions
Posted: Fri Oct 14, 2022 1:27 am
by lortega
I'm following along the meaty skeleton tutorial and had a few questions about the header file conventions used. Unfortunately, seems the account that created it is no longer active, so I'm hoping others are aware of the conventions being used.
I see three distinct conventions used on the include guards in this tutorial, they are:
- all caps version of the filename, including extension
- all caps name including preceding underscore and library name (e.g. "_KERNEL_TTY_H")
- the second convention, but with the define having a "1" after the guard name
For anyone who's viewing this thread in hopes of learning about the conventions, here's an explanation of the first two. The first rule is fairly standard, by naming your preprocessor guard like this, you avoid naming conflicts with other headers. The second rule is used since that particular header is being compiled as part of libc, and convention holds that global headers have this preceding underscore to further avoid conflict with project specific headers. If anyone has any corrections or clarifications on this, please let me know.
My question is mostly about the third rule I listed. Why is the "1" following the define? The author of that page said most elements of their code is intentional, even the weirder ones, as they either directly serve a purpose for the tutorial, or help to simplify future work. I tried searching for this convention but could not find anything about it.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 2:43 am
by max
There is no further intention behind this. #ifndef will only check if the symbol is (not) defined, the value does not matter.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 4:53 am
by Solar
lortega wrote:The second rule is used since that particular header is being compiled as part of libc, and convention holds that global headers have this preceding underscore to further avoid conflict with project specific headers. If anyone has any corrections or clarifications on this, please let me know.
Any kind of identifier that begins with two underscores, or one underscore and an uppercase letter, is "reserved for the implementation", i.e. not legal in application code. (There are more reserved identifiers, like E_*, but they are reserved for different purposes.)
"The implementation" used to be the combination of compiler and library. Since compiler and library could conceivably come from two different upstreams, you have to "hope" that they don't use the same identifier for different things. Prefixing identifiers with _MYCLIB_* or _MYCOMPILER_* reduces that probability to next-to-zero.
lortega wrote:My question is mostly about the third rule I listed. Why is the "1" following the define?
Safeguard against being lazy. It makes no difference for #ifdef / #ifndef, but if you just wrote #if, having the identifier defined to 1 will give you a true result, while having it defined to empty will give you a somewhat funky error message.
There's yet another convention, that is to define the header guard
to itself.
Code: Select all
#ifndef MYAPP_MAIN_H
#define MYAPP_MAIN_H MYAPP_MAIN_H
In the (admittedly far-fetched) case that someone wanted to use MYAPP_MAIN_H as a variable or function name, both "#define MYAPP_MAIN_H" and "#define MYAPP_MAIN_H 1" would cause a compilation error, while the above construct doesn't.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 7:13 am
by iansjack
Excellent explanation.
But it would be more consistent to stick to one convention (use 1 everywhere or use 1 nowhere) rather than mixing styles.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 10:36 am
by kzinti
Here is another convention:
Although 'non-standard", it is effectively supported by all compilers.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 1:26 pm
by nullplan
kzinti wrote:Although 'non-standard", it is effectively supported by all compilers.
I would disagree. It is not supported by at least one compiler I use regularly, and that is one more than has an issue with normal include guards. Clang, GCC, and MSVC make up a large chunk of the compiler market, but they are not all of it.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 3:03 pm
by kzinti
Not many people get to work on OS-9. Lucky you.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 3:13 pm
by lortega
Wow thanks everyone so many quick responses! Glad to see its just a separate convention and not some alternate functionality I was missing. In that case, I'll do what makes the most sense to me and was suggested in this thread, and go along with using the same style (so no "1" for me). I understand it helps if someone uses #if rather than #ifdef, but thats not something I would personally use nor any collaborators I can think of, so seems to make more sense just to stick to a programming style that makes the most sense for me.
Re: C Header File conventions
Posted: Tue Oct 18, 2022 9:15 pm
by nullplan
kzinti wrote:Not many people get to work on OS-9. Lucky you.
I feel so privileged.
...he said, bitterly, as he waited another five minutes for the bloody prelinker to finish.
Re: C Header File conventions
Posted: Wed Oct 19, 2022 2:32 am
by Solar
kzinti wrote:Here is another convention:
Although 'non-standard", it is effectively supported by all compilers.
And I've run into problems with that at least twice (once in the context of softlinked header files, once in the context of a header file being copied into several locations of the source tree). I don't really get why anyone would go for a #pragma of
any kind for something that can be done perfectly well without.
Re: C Header File conventions
Posted: Wed Oct 19, 2022 4:07 am
by kzinti
Solar wrote:once in the context of softlinked header files
Yes I can see how that could be a problem... As I understand it GCC and clang both handle them properly.
Solar wrote:once in the context of a header file being copied into several locations of the source tree).
Your problem here is that you copied the same header file in several locations, not that you used #pragma once. You could also run into issues with #ifdef/#define if you modified one of these file and forgot to update the other locations. Did you end up copying the file because of the softlink issue above?
Solar wrote:I don't really get why anyone would go for a #pragma of any kind for something that can be done perfectly well without.
- Can reduce build time as the compiler doesn't need to open and read the same file again after the first #include of the file in the translation unit.
- Doesn't pollute the global namespace with header guards
- Less error prone
- Less maintenance on the programmer's part
In my experience, I've run into problems with header guards a few times where I've only hit one issue with #pragma once: a compiler that didn't support it in a cross-platform project.
More info here:
https://en.wikipedia.org/wiki/Pragma_once
Re: C Header File conventions
Posted: Wed Oct 19, 2022 8:56 am
by Solar
kzinti wrote:Solar wrote:once in the context of a header file being copied into several locations of the source tree).
Your problem here is that you copied the same header file in several locations, not that you used #pragma once. You could also run into issues with #ifdef/#define if you modified one of these file and forgot to update the other locations. Did you end up copying the file because of the softlink issue above?
The issue was that the
developer thought that "same file name, same contents" would make the compiler consider it the same file and thus avoid redeclaration / redefinition issues. Whereas the compiler considered those separate files.
You're losing a level of control with #pragma once.
kzinti wrote:Solar wrote:I don't really get why anyone would go for a #pragma of any kind for something that can be done perfectly well without.
- Can reduce build time as the compiler doesn't need to open and read the same file again after the first #include of the file in the translation unit.
GCC does not re-read header files since
at least version 3.0...
kzinti wrote:
- Less error prone
To the contrary, which was the reason for my comment. I
despise "automagic" solutions to non-existing problems, because when
those go awry, finding out what your actual problem is can be orders of magnitude more annoying than e.g. a mistyped header guard.
(Have you ever had a hash collision in a Git repository? I have. No fun.)
kzinti wrote:In my experience, I've run into problems with header guards a few times...
All of which boil down to
developer error, not
compiler quirk...
kzinti wrote:...where I've only hit one issue with #pragma once: a compiler that didn't support it in a cross-platform project.
Well, cross-platform is pretty much all I am doing, and in some cases with some
really old compiler. (Dice C on the Amiga.)
Gee, look at the "Caveat" section! Pretty much exactly what I wrote above!
Re: C Header File conventions
Posted: Wed Oct 19, 2022 10:21 am
by kzinti
You got me thinking and now I don't think one method is (much) better than the other. They both have pros and cons. I just wanted to bring it up as another option since this was the subject of this thread.
Re: C Header File conventions
Posted: Fri Oct 21, 2022 5:54 pm
by thewrongchristian
I use
makeheaders, from the same guy that wrote SQLite.
Makes header management a breeze. Each source file has a single header (plus any compiler/system headers required), and that single head is generated from the sources.
If one source file references a function defined in another source file, that function is prototyped and inserted into the source's header file. It makes my C source really easy to manage.
Re: C Header File conventions
Posted: Mon Oct 24, 2022 8:22 am
by eekee
Some years ago I read that slow compilation was considered one of C++'s bigger problems, and that re-including header files was part of the reason it was so slow. Guards don't really help with this; the preprocessor still has to parse the entire file every time its loaded to find the correct #endif. I assume #pragma once is an attempt to deal with this speed issue. That's the only positive thing I have to say about it, anyway.