Skip to content

Conversation

@colinleach
Copy link
Contributor

The Lasagna exercise surfaced some concerns in the team about when/how to introduce header files. I've drafted one suggestion for discussion. I aimed for it to be relatively short and gentle, suitable for quite early in the syllabus.

Copy link

@rmonnet rmonnet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read through the explanation in about.md and introduction.md (I am assuming the second file goes in the exercise for the headers-include concept) and I found the explanation pretty clear overall. In my mind, there are a couple of points that may bring confusions in the mind of a C beginner.

The explanation is clear but makes me wonder if you may need to include an additional concept for the C pre-processor itself and have it as a prerequisite to visit the headers-include concept. There is quite a bit to say about the pre-processor itself and mentioning it just as an aside in the header discussion may make it confusing for a C beginner. (It is kind of a chicken-and-egg problem and it is quite difficult to untangle the header files from the preprocessor).

When discussing the Include Guard, the C hello world mention that you can use #pragma once instead. That would be confusing for a beginner since there is no mention of the #pragma once except for that comment. Personally, I think there is enough material in your introduction and adding more details may be counter-productive. My suggestion would be to remove the comment on #pragma once from the hello_world.h header and your concept doc, or at least, remove it, from your about.md and introduction.md to keep your text clear. If you had a concept on the preprocessor, this may be a good place for it. (By the way, if you are going to keep mentioning it in the hello_world.h, you can link to https://en.wikipedia.org/wiki/Pragma_once the same way you linked to the Wikipedia Include_Guard entry.

I think you have a typo on line 79 in about.md "Including system headers is very common in C code, even in simple cases like..."

@siebenschlaefer
Copy link
Contributor

Hi Colin, are you open to feedback?

@colinleach
Copy link
Contributor Author

Sure, I'm happy with feedback. Though a bit surprised - this syllabus didn't seem to be progressing much, so I assumed there was limited interest.

Perhaps the bigger problem is that a variety of health problems over the past couple of months have meant I've been very unproductive. There's a big backlog of Julia and Kotlin stuff I should have been working on. Annoying...

@@ -0,0 +1,92 @@
# About

C requires that all functions are declared _before_ they are defined.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C requires functions to be declared before they are called or otherwise used in an expression. It's valid to define functions without declaring them first.
There is however the compiler option -Wmissing-declarations that warns about non-static(!) functions that are defined without being previously declared. The idea is that there are typically two kinds of functions, those declared in a .h file and meant to be called from other .c files, and local (static) helper functions that are effectively hidden from other translation units. The latter can be defined without a prior declaration and -Wmissing-declarations will not complain.

Did you want to write "called" instead of "defined"?


A header file can range from just a few lines to several hundred.

For a simple example, we can look at the `Hello World` exercise (which you already completed). This is the [`hello_world.h` file][hello-h] which is part of that exercise:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one line per sentence


Most of it is explanatory comments (lines starting with `//`).

### Declarations
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this whole section. It talks about parameters but not about the name or return type.
If this is the main explanation of function declarations I would like it to be more extensive.
But is this really the place for that? I'd prefer a separate concept for functions that also covers function declarations.


This function takes no parameters (indicated by [`void`][void]).

Most functions have parameters, so these:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO "these" is ambiguous here. How about "their declarations"?


### Guards

Lines beginning with `#` are preprocessor directives, to ensure that the compiler only includes the header file once.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence can be interpreted as "Preprocessor directives ensure that the compiler only includes the header file once." But the preprocessor can do much more than that. How about splitting the sentence into two? The first part up to "directives" talks about preprocessor directives in general, and the second sentence explains the include guard.

There are two variants of `#include`:

- Those in double-quotes, as above, tell the compiler to search the project directory for the header file.
- Those in brackets, such as `#include <math.h>`, are for items in the standard library. The compiler will search for these in a central location, such as `\usr\include` (on Ubuntu systems).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Officially both variants (double quotes and angle brackets) tell the the compiler to search for a header in two (potentially completely different) implementation-specific locations. One important difference is that if #include "h-char-sequence" is not supported or fails it falls back to #include <h-char-sequence>
In practice, #include "some_filename" first searches the local file and then behaves like #include <some_filename>.

- Those in double-quotes, as above, tell the compiler to search the project directory for the header file.
- Those in brackets, such as `#include <math.h>`, are for items in the standard library. The compiler will search for these in a central location, such as `\usr\include` (on Ubuntu systems).

Including system headers is very common in C code, even simple cases like an Exercism toy exercise.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Including system headers is very common in C code, even simple cases like an Exercism toy exercise.
Including system headers is very common in C code, even in simple cases like an Exercism toy exercise.


Including system headers is very common in C code, even simple cases like an Exercism toy exercise.

Common examples include `stdio.h` (_for printing, etc_), `string.h`, `math.h`, `stdlib.h` (_for various C99 standard library functions_).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest omitting "C99".

This can be done at the top of the `*.c` file containing the definition, but there are advantages in splitting declarations into a separate header file with a `.h` extension.

You can think of the header file as an API.
The header will tell you _what_ a codebase has to offer, without going into the details of _how_.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer "interface" instead of "API" because I believe it's easier to understand for people who don't know what an "API" is. But that's not a strong preference.
I believe these two sentences are the most important part of this document, the rest are technical details. I would love to see this part fleshed out.


Many other things can be included in a header file, and you will see examples later in the syllabus.

### Guards
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer "Include Guards" instead of "Guard", like in the rest of this document.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants