C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
72: The #include Directive: Angle Brackets vs Quotes
I see this a lot when I'm reviewing code from developers moving into C: they treat the choice between <header.h> and "header.h" as a semantic rule. They think the brackets are a "flag" that tells the compiler, "This is a system library," and the quotes are a flag saying, "This is a file I wrote."
"Quotes are for local files, brackets are for system libraries"
If you believe that, you're thinking about it as a category of file rather than a search instruction. Let me show you why that's a misconception. Imagine you have a project with a local header called physics_engine.h. You've been using #include "physics_engine.h" because that's the "local" way.
But what happens if you run your compiler with an include flag, like -I./include, and you move that header into that directory? Suddenly, #include <physics_engine.h> works perfectly. The compiler doesn't suddenly think your physics engine is part of the C Standard Library; it just found the file using the path you provided. Conversely, if you accidentally copy stdio.h into your project folder, #include "stdio.h" will include your local copy instead of the system one, potentially breaking everything.
It's actually about the search priority
The real difference is the order of operations the preprocessor uses to find the file. When you use quotes, you're telling the compiler: "Start looking in the directory where this current source file lives. If you don't find it there, then go look in the system include paths."
When you use angle brackets, you're skipping the local directory entirely. You're saying: "Go straight to the system paths (and any paths I've added via the -I compiler flag)."
// The search logic looks roughly like this:
#include "my_lib.h"
// 1. Check local folder -> Found? Stop.
// 2. Check -I paths -> Found? Stop.
// 3. Check /usr/include (etc) -> Found? Stop.
// 4. Error.
#include <my_lib.h>
// 1. Check -I paths -> Found? Stop.
// 2. Check /usr/include (etc) -> Found? Stop.
// 3. Error.
I usually stick to the "convention" of brackets for system headers and quotes for project headers, but I do it because it signals intent to other humans, not because the compiler requires it for "system" vs "local" files. The crucial takeaway for you is that quotes are a superset of brackets—they do everything brackets do, but they check the local directory first.
One pro tip: avoid using quotes for standard headers like <stdlib.h>. Even if it works, it's a red flag during code reviews because it suggests you might have a naming collision in your local directory that you're unaware of.
📋 Practical Task
Fixing the Header Search Collision in a Math Library
You are working on a project where a teammate accidentally created a file named math.h in the local project directory. This is colliding with the system's <math.h> (which contains sin() and cos()).
Below is a snippet of main.c. The goal is to use the system's sqrt() function from the standard library, but the program is currently including the local, empty math.h instead, causing a compilation error because sqrt is not defined.
// Project structure:
// /project/main.c
// /project/math.h <-- An empty file created by mistake
#include <stdio.h>
#include "math.h" // This is causing the problem
int main() {
double val = 25.0;
printf("Square root is: %f", sqrt(val));
return 0;
}
Your Task: Modify the #include directive for the math library so that the compiler ignores the local math.h and forces the use of the system's standard math library. Explain why this change fixes the issue based on the search priority rules.
There are no comments for now.