Ce face #include
#include îi cere preprocesorului să pună, exact în acel loc, tot conținutul altui fișier. Așa ajung în program declarațiile din biblioteca standard: #include <stdio.h> aduce declarația lui printf, #include <string.h> pe cea a lui strlen.
Cu paranteze unghiulare (<stdio.h>) fișierul este căutat în directoarele sistemului. Cu ghilimele ("note.h") este căutat întâi lângă fișierul curent, apoi în directoarele sistemului. Directoare în plus se adaugă cu opțiunea -I a compilatorului.
Un antet poate ajunge inclus de mai multe ori (direct și prin alt antet). Ca definițiile să nu apară de două ori, fiecare antet se scrie cu o gardă de includere: #ifndef NOTE_H / #define NOTE_H / … / #endif. La a doua includere, NOTE_H este deja definit și conținutul este sărit. #pragma once face același lucru și este acceptat de GCC, Clang și MSVC, dar nu face parte din standard.
Parametri
| Parametru | Descriere |
|---|---|
<fisier.h> |
Antet al sistemului sau al unei biblioteci instalate, căutat în directoarele standard. |
"fisier.h" |
Antet al proiectului, căutat întâi în directorul fișierului care îl include. |
Exemple
Exemplul 1: Fiecare funcție are nevoie de antetul ei
printf vine din <stdio.h>, strlen din <string.h>, toupper din <ctype.h>. Fără antetul potrivit, compilatorul nu cunoaște funcția și oprește compilarea.
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char oras[] = "iasi";
oras[0] = (char)toupper((unsigned char)oras[0]);
printf("%s are %zu litere\n", oras, strlen(oras));
return 0;
}
Rezultat
Iasi are 4 litere
Exemplul 2: Cum funcționează garda de includere
Aici conținutul unui antet produs.h este scris de două ori în același fișier, cum s-ar întâmpla dacă ar fi inclus de două ori. A doua oară, PRODUS_H este deja definit, deci struct produs nu este redefinit și programul se compilează.
#include <stdio.h>
// --- prima includere a lui produs.h ---
#ifndef PRODUS_H
#define PRODUS_H
struct produs {
const char *nume;
double pret;
};
#endif
// --- a doua includere (de exemplu, prin alt antet) ---
#ifndef PRODUS_H
#define PRODUS_H
struct produs {
const char *nume;
double pret;
};
#endif
int main(void) {
struct produs p = {"caiet", 7.5};
printf("%s: %.2f lei\n", p.nume, p.pret);
return 0;
}
Rezultat
caiet: 7.50 lei
Exemplul 3: Antet propriu cu #pragma once
Un proiect cu mai multe fișiere: note.h conține doar declarația, note.c definiția, iar main.c include antetul cu ghilimele. Detalii pe pagina fișiere antet.
// note.h
#pragma once
double media(const int note[], int n);
// main.c
#include <stdio.h>
#include "note.h"
int main(void) {
int note[] = {9, 10, 8, 7};
printf("Media Anei: %.2f\n", media(note, 4));
return 0;
}
// în terminal:
// clang -std=c23 -Wall main.c note.c -o catalog && ./catalog
Ieșire în terminal
Media Anei: 8.50
Greșeli frecvente
- Incluzi un fișier
.c(#include "note.c"). Codul ajunge compilat de două ori și apar erori de tipul „duplicate symbol” la legare. Include doar antete.hși compilează fiecare.cseparat. - Pui definiții de variabile sau funcții în antet (
int total = 0;). Fiecare.ccare include antetul primește propria copie. În antet pune doar declarații (extern int total;). - Folosești același nume de gardă în două antete. Al doilea antet este sărit fără niciun mesaj. Pune în gardă numele fișierului:
NOTE_H,PRODUS_H.
Comenzi înrudite
Programe din mai multe fișiere (.c și .h): Cum împarți un program C în fișiere sursă (.c) și antete (.h), cum le compilezi separat și cum le legi într-un executabil.#if, #ifdef, #ifndef: Compilare condiționată: preprocesorul păstrează sau elimină bucăți de cod în funcție de macro definite sau de valoarea lor.#define: Definește o macro: un nume pe care preprocesorul îl înlocuiește cu textul dat, înainte ca programul să fie compilat.extern: Declară o variabilă globală definită în alt fișier (sau mai jos), ca să o poți folosi fără să creezi o copie nouă.Compilarea cu gcc și clang: Cum transformi codul C într-un program executabil cu gcc sau clang și ce fac opțiunile folosite cel mai des.