5

I have a project with a src and an include directory. When compiling, I pass the include directory via the -I option (gcc -Iinclude ...).

Should I use double quotes (") or angle brackets (<) to include my own header files?


I tried to look for an answer and found these two conflicting statements:

  1. include header files relative to the c file via double quotes. Everything else (header files in include paths) with angle brackets. -> thus use angle brackets
  2. include standard headers with angle brackets. Everything else with double quotes. -> thus use double quotes

In my opinion statement 2 is clearer. When including a file with double quotes it is most obvious that it is my own header.


Should I use quotes or brackets to include my own header files? The C standard allows both possibilities. So what is the best practice?

user5534993
  • 518
  • 2
  • 17
FooBaron
  • 53
  • 4
  • 1
    "two conflicting statements" - they don't seem to be conflicting, though. They both say that you should include your headers (which are assumed to be part of your project and thus relative to the C file) with double quotes, and everything else, including standard headers, - with angle brackets. – ForceBru Jan 13 '21 at 11:09
  • This statement was unfortunately worded. What relative to your c file meant was to include it by `#include "../include/header.h"`. So statement 1 would say that I should include it with angle brackets – FooBaron Jan 13 '21 at 11:12
  • The choice is a style preference. And, as with all style preferences, there are conventions and conflicting camps. Use double quotes. – William Pursell Jan 13 '21 at 11:28

3 Answers3

2

The common convention is:

  • Use < … > for headers that are part of the C implementation or the platform—headers outside your project such as the C standard library, Unix or Windows headers, and headers of libraries generally installed for your development environment.
  • Use " … " for headers that are part of your project.

This is not fully determined by the C standard; it is a matter of general practice. For each delimiter choice, a compiler has a list of places (a search path) where it looks for headers. Those search paths are commonly designed to facilitate the use described above, but they are customizable (depending on the compiler you use) by command-line switches, by environment variables, by system settings, and/or by settings made when building the compiler.

Here is what the C standard says about them in C 2018 6.10.2. Paragraph 2 says:

A preprocessing directive of the form

# include < h-char-sequence > new-line

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

Paragraph 3 says:

A preprocessing directive of the form

# include " q-char-sequence " new-line

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

# include < h-char-sequence > new-line

with the identical contained sequence (including > characters, if any) from the original directive.

Note some of the differences between the two:

  • The text for the bracket form says it searches for a header identified uniquely. The text for the quote form does not include the word “uniquely”. This suggests all the headers referred to by the bracketed form are supposed to be different from each other, which you might expect if they were part of a designed system seeking to avoid ambiguity.
  • Note that it says the first form “searches a sequence of implementation-defined places.” This accords with the compiler having a list of places to search for standard headers. For the second form, it uses “the source file identified by the specified sequence.” This accords with using the text between quotes as a path in the file system.

This text in the standard is quite lax, both allowing implementation-defined methods of identifying the files, so either can be stretched to be the same as the other (although it would be interesting to see a compiler complain that a header named in brackets is not unique), and compiler configuration options are sufficiently broad that you could use each in either way for your project. However, it is generally better to stick to convention.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Consider this example:

+- include/
|  |
|  \- header.h
|
+- src/
   |
   \- main.c

The statements are saying to either use:

#include "../include/header.h"

gcc src/main.c

or:

#include <header.h>

gcc -Iinclude src/main.c

You decide which style to use. I personally prefer the second one. But it more important to use a consistent style throughout the project.

sergej
  • 17,147
  • 6
  • 52
  • 89
  • 2
    You could also do #include "header.h" and add the -Iinclude argument to the gcc call. My question is whether I should use double quotes instead of the brackets, so it is clear, that the header is something project related. – FooBaron Jan 14 '21 at 09:43
0

The first statement in your question fits to the rule SF.12 of the C++ Core Guidelines in its current version:

Prefer the quoted form of #include for files relative to the including file and the angle bracket form everywhere else

Although it conflicts with the recommendation of 15.3 Note 1 of the Standard for C++23 (draft N4928):

using the < > form for headers provided with the implementation and the " " form for sources outside the control of the implementation achieves wider portability

I recommend you to apply SF.12 as it can reduce the risk of including the wrong file, as they explain:

Failing to follow this results in difficult to diagnose errors due to picking up the wrong file by incorrectly specifying the scope when it is included. For example, in a typical [compiler implementation] where the #include "" search algorithm might search for a file existing at a local relative path first, then using this form to refer to a file that is not locally relative could mean that if a file ever comes into existence at the local relative path (e.g. the including file is moved to a new location), it will now be found ahead of the previous include file and the set of includes will have been changed in an unexpected way.

If the < > would have been used instead, the path relative to the including file would not have been searched (for typical compiler implementations) and thus the above described case would not have been an issue.

Or more generally speaking: If the compiler implementation would find the file with both forms, use the form which has less potential for ambiguity. As < > is a fallback for " " (per standard), " " will search at potentially more places. Thus use < > where possible.

Although the common convention differs. SF.12 provides a technical reason to deviate slightly from that convention.

user5534993
  • 518
  • 2
  • 17