Bežné chyby v C: ako čítať hlášky a kde hľadať opravu
Chybové hlášky nie sú útok proti tebe – sú to presné súradnice problému. GCC v drvivej väčšine prípadov povie presne, čo je zle a často aj ako to opraviť. Tento návod ťa naučí tie hlášky čítať a na reálnych príkladoch ukazuje najčastejšie chyby v C. Všetky výpisy tu sú skutočné správy z kompilácie aj z behu programov (gcc 16 – staršie verzie bývajú o slovo iné, duch sa nemení).
Ako čítať hlášku od gcc
typo.c:4:20: error: 'pocet2' undeclared (first use in this function); did you mean 'pocet'?
4 | printf("%d\n", pocet2);
| ^~~~~~
| pocet| Časť hlášky | Význam |
|---|---|
typo.c:4:20 | súbor, riadok, stĺpec – presné miesto, kde si kompilátor všimol problém |
error: / warning: / note: | error musíš opraviť; warning by si mal opraviť; note obsahuje radu |
'pocet2' undeclared | čo je problém – tu: nepoznáš premennú pocet2 |
did you mean 'pocet'? | novší gcc navrhuje opravu priamo |
| šípka pod riadkom | ukazuje presne na problémový úsek kódu |
Pri viac súboroch vidíš aj reťazec include-ov:
In file included from twice.c:2:
noguard.h:1:8: error: redefinition of 'struct Bod'
1 | struct Bod { int x; int y; };
| ^~~
In file included from twice.c:1:
noguard.h:1:8: note: originally defined herePovie ti to: struct Bod som videl dvakrát – prvý výskyt (pri note:) je originál, druhý je duplikát,
aký máš odstrániť.
Pravidlá čítania:
- Opravuj prvú chybu, nie poslednú. Jedna chýbajúca bodkočiarka dokáže vyvolať 15 errorov – po jej oprave väčšina zmizne.
- Chyba na riadku N často znamená chybu na riadku N-1. Napr.
expected ',' or ';' before 'int'na riadku 4 vznikla preto, že riadok 3 nekončí;. - Čítaj
note:. Často v nej stojí odpoveď priamo („include<math.h>or provide a declaration ofsqrt"). - Warning je budúci error.
gcc -Wall -Wextrati ukáže skutočné problémy zadarmo; neignoruj ich. - Hlášku hľadaj na internete v presnom znení – bez cesty k tvojmu súboru.
Preklepy a deklarácie
❌ Premenná, ktorú gcc nepozná (undeclared)
error: 'pocet2' undeclared (first use in this function); did you mean 'pocet'?Premenná neexistuje – buď je preklep, alebo si ju zabudol deklárovať, alebo je v inom rozsahu (lokálna z inej funkcie). Novší gcc rovno radí opravu.
❌ Chýbajúca bodkočiarka
semicolon.c:4:5: error: expected ',' or ';' before 'int'
4 | int b = 2
| ^~~Tip: bodkočiarku hľadaj na predchádzajúcom riadku. Chýbajúca bodkočiarka v .h sa často ukáže až
v .c, ktoré hlavičku includuje.
❌ Duplicitná definícia (struct dvakrát)
error: redefinition of 'struct Bod'
note: originally defined hereHlavička bola includnutá dvakrát. Oprava: include guard v každej .h:
#ifndef STATISTIKA_H
#define STATISTIKA_H
/* sem patria deklarácie */
#endifHlavičky a viac zdrojových súborov
❌ Implicitná deklarácia funkcie
implicit.c:3:16: error: implicit declaration of function 'sqrt' [-Wimplicit-function-declaration]
implicit.c:2:1: note: include '<math.h>' or provide a declaration of 'sqrt'Voláš funkciu, ktorej prototyp kompilátor nevidí. Príčiny: chýbajúci #include (matika → <math.h>,
reťazce → <string.h>), preklep v mene, alebo funkcia definovaná až za volaním bez deklarácia. Na starších
gcc je to len warning – a presne takéto varovania vedú k nepochopiteľným výsledkom, lebo si gcc
návratový typ odhadol.
❌ undefined reference
/usr/bin/ld: main.c:(.text+0xa): undefined reference to `zdvoj'
collect2: error: ld returned 1 exit statusChyba linkera, nie kompilátora: prototyp existoval a kompilátor ho videl, ale telo funkcie nikto nepridal. Najčastejšie:
- zabudol si pridať druhý
.cdo príkazu (gcc ... main.c helper.c, nie lenmain.c), - chýbajúca knižnica –
-lmaž za zdrojovými súbormi (podrobnosti v návode Inštalácia kompilátora GCC), - definícia funkcie nie je nigde (iba v hlavičke, alebo vôbec).
❌ multiple definition
b.c:(.text+0x0): multiple definition of `pocet'; /tmp/cchd8h4e.o:a.c:(.text+0x0): first defined hereFunkcia (alebo globálna premenná) je definovaná v .h súbore a ten sa cez #include ocitne vo dvoch .c. Definícia
má byť v práve jednom .c; v hlavičke je len deklarácia (int pocet(void);). Výnimka: static funkcia alebo
static inline.
Formátované vstupy a výstupy
❌ scanf bez &
warning: format '%d' expects argument of type 'int *', but argument 2 has type 'int' [-Wformat=]
5 | scanf("%d", vek);scanf potrebuje adresu, kam má písať. Chýbajúce & je veľmi častá príčina segfaultu v úlohách z
cvičení. Správne: scanf("%d", &vek);.
❌ Formát nesedí s typom
warning: format '%d' expects argument of type 'int', but argument 2 has type 'double' [-Wformat=]
4 | printf("d = %d\n", d);
| int double
| %fNovší gcc vypíše rovno aj odporúčaný náhradu formátu (v ukážke pre double radí %f). Základná tabuľka:
| Formát | Patrí na | Pozor |
|---|---|---|
%d | int | – |
%f | double | pri scanf musí byť %lf, pri printf stačí %f |
%c | char | scanf: %c nepreskakuje medzery/newline na rozdiel od %d a %s |
%s | pole znakov (char*) | vždy s rozmerom, napr. %20s |
%p | pointer | printf – výpis adresy, napr. &premenna |
%% | znak % | printf |
Chyby, ktoré ukáže až beh
❌ Segmentation fault
bash: line 1: 51673 Segmentation fault (core dumped) ./programProgram siahol mimo svoju pamäť. Typické príčiny: scanf bez & (hore), dereferencovaný NULL smerník,
neinicializovaný smerník, prístup za koniec poľa, zápis do reťazcového literálu (char *s = "text"; s[0] = 'x';).
Cez exit kód: echo $? povie 139 (= 128 + signál 11).
Kde hľadať miesto: gcc ... -g a gdb ./program → run, bt (backtrace ukáže funkciu aj riadok), alebo
kompilácia s -fsanitize=address – tá vypíše presný riadok a typ chyby pamäte. Obe techniky sú v návode
Inštalácia kompilátora GCC.
❌ Delenie nulou
bash: line 1: 51690 Floating point exception (core dumped) ./programCeločínske delenie nulou (5 / 0) ukončí program signálom SIGFPE (exit 136). Reálne číslo nulou
nedelí – program beží ďalej a dostaneš prekvapivé hodnoty:
printf("%f %f\n", 1.0 / 0.0, 0.0 / 0.0); /* → inf -nan */Ošetrenie je obyčajné if z cvičení: if (deaths == 0) ....
❌ Reťazce porovnané cez ==
warning: comparison with string literal results in unspecified behavior [-Waddress]A aj keby varovanie nebolo – logika je zlá. odp == "ano" porovnáva adresy, nie obsah; aj keď používateľ
zadá „ano", výstup je NIE. Reťazce sa porovnávajú funkciami strcmp() / strncmp() z <string.h>.
❌ Neinicializovaná premenná
warning: 'sucet' is used uninitialized [-Wuninitialized]
note: 'sucet' was declared hereV premennej je len náhodný zvyšok z pamäte – výsledok vyzerá „takmer správne" a mení sa s každým rebuildom.
Vždy inicializuj: int sucet = 0;.
Ako nájsť miesto problému v kóde
- Čítaj od prvej hlášky: tá je najcennejšia – ďalšie môžu byť len jej dozvuk.
- Pozri o riadok vyššie, než píše kompilátor.
- Vynechaj polovicu kódu – po častiach zistíš, kde sa to rozbilo (alebo pozri
git diff). - Vypisuj si medzivýsledky:
printf("i=%d, sucet=%d\n", i, sucet);je primitívne, ale funkčné ladenie. - Zadaj vstup, o ktorom vieš, že má konkrétny výstup – potom sa posúvaj od vstupu k chybe.
- Nakresli si to – pri smerníkoch a poliach jeden štvorec s šípkou nahradí 20 riadkov kódu.
Kde hľadať opravu
V tomto poradí:
- Poznámka od gcc – často obsahuje priamu odpoveď (
did you mean,include '<math.h>',use option '-std=c99'...). man– manualovú stránku máš v termináli:man 3 scanf,man 3 strcmp. Vysvetlí formáty aj chybové stavy.- Príklady na stránke predmetu – Príklady obsahujú funkčné ukážky k každej téme (polia, smerníky, súbory, rekurzia).
- cppreference.com – najúplnejšia referencia C knižníc; hľadaj podľa názvu funkcie.
- Vyhľadávanie – vlož presný text chyby (bez svojej cesty k súboru) do vyhľadávača.
- AI nástroje – v tomto predmete povolené na inšpiráciu, riešenie problémov a testovanie; priame
generovanie riešenia zadania je zakázané (pozri pravidlá v zadaniach). Pýtať sa AI „prečo táto hláška
vznikla" je OK; požiadať ju o hotový
main.cnie. - Cviaci – MS Teams alebo email; posielaj konkrétnu hlášku a kód, nie „nejako to nefunguje".
Rýchly referenčný list
| Hláška | Príčina | Oprava |
|---|---|---|
undeclared ... did you mean | preklep / chýba deklarácia | oprav meno, doplň #include |
expected ',' or ';' before ... | chýba bodkočiarka o riadok vyššie | dopln ; |
redefinition of 'struct' | hlavička bez guardu | #ifndef / #define / #endif |
implicit declaration of function | chýba #include alebo prototyp | pripoj hlavičku, oprav meno |
undefined reference | linker nevidí definíciu | pridaj .c do príkazu / -lm za súbory |
multiple definition of | definícia v .h includnutá 2× | definícia len v jednom .c |
expects argument of type 'int *' | scanf bez & | scanf("%d", &x) |
expects argument of type 'int', ... 'double' | %d na double | %f, pri scanf %lf |
Segmentation fault (core dumped) | siahanie mimo pamäť | -g + gdb / ASan; skontroluj pointere a medze polí |
Floating point exception (core dumped) | celočíselné delenie nulou | ošetri if (menovatel == 0) |
comparison with string literal | reťazec porovnaný cez == | strcmp() |
used uninitialized | inicializácia chýba | int x = 0; |
Ďalšie zdroje
- Návod Inštalácia kompilátora GCC – flags, linkovanie, ladenie, sanitizery
- Návod Štruktúra C projektu a Makefile – viac súborov bez linkerových prekvapení
- C reference – cppreference.com – jazyk a knižnice dohromady
- GNU GCC Manual – Invoke GCC – prepínače a diagnostika