Překlad jazyka C Plus Plus

Z CHWiki

Přejít na: navigace, hledání

C a C++ jsou poměrně nízkoúrovňové jazyky a vedle problémů s programem samotným mívají začátečníci i problémy s překladem. Většinou nestačí použít k řešení intuici a je třeba vědět, jak v C/C++ probíhá překlad. V obou jazycích je základní proces v podstatě stejný.

Překlad má následující základní fáze:

  1. Předzpracování zdrojového kódu (preprocessing)
  2. Překlad jednotlivých zdrojových souborů (compilation)
  3. Spojování (linking)

Obsah

[editovat] Předzpracování (preprocessing)

Tuto fázi zajišťuje program zvaný preprocessor. Projde všechny zdrojové soubory a provede expanzi maker a zpracuje instrukce pro preprocessor. Tyto instrukce vždy začínají znakem # na začátku řádku. Nejčastěji se používají tyto instrukce:

#include "soubor.h"

Tato instrukce vloží celý obsah soubor.h na dané místo.

#define MAKRO obsah

Tato instrukce nadefinuje makro s názvem MAKRO a jako jeho obsah nastaví obsah. Kdekoliv se potom ve zdrojovém souboru bude vyskytovat řetězec MAKRO, bude nahrazen obsahem tohoto makra. Makra mohou mít i parametry.

#ifdef MAKRO

Pokud je makro s názvem MAKRO definováno, bude následující kód ponechán, jinak bude až do #endif odstraněn.

Do překladače jde až zpracovaný zdrojový kód.

[editovat] Překlad (compilation)

Předzpracované zdrojové soubory (ty s příponou cpp nebo c) jsou jeden po druhém přeloženy překladačem do tzv. objektových souborů (přípona .obj nebo .o, nijak to nesouvisí s objektově orientovaným programováním). Každý soubor je přeložen zvlášť a nezávisle na ostatních. Funkce, objekty a proměnné mají v objektovém souboru svůj název (který může být ale překladačem pozměněn, především v případě C++).

Z toho důvodu nemůže překladač odhalit, když jsou dvě proměnné stejného jména deklarované ve dvou souborech a podobně.

[editovat] Spojování (linking)

Nakonec linker vezme objektové soubory a spojí je do jednoho spustitelného souboru nebo knihovny. Během tohoto procesu nahradí odkazy pomocí názvů konkrétními adresami.

V této fázi lze detekovat duplicitní funkce, proměnné a podobně.

[editovat] Obvyklé problémy

Unresolved external symbol ...
Tuto chybu hlásí linker když v objektovém souboru najde odkaz na funkci nebo proměnnou, která není nikde definována. Typicky je to v případě, kdy v jednom zdrojovém souboru voláte funkci, k níž máte hlavičku, ale chybí tělo. Anebo je tělo definováno v souboru, který jste zapomněli do překladu zařadit.
Tuto chybu také dostanete, pokud budete používat externí knihovnu a zapomenete ji přilinkovat (použít hlavičkové soubory nestačí).
Pokud symboly neznáme a obsahují slova jako dbg, debug apod., může jít o konflikt verze C Runtime knihovny, kterou používá váš projekt a se kterou byly zkompilovány cizí knihovny. Je třeba použít stejné verze.
Příklad, kde se tento problém vyskytne:
// Tato hlavička funkce bude typicky v includovaném hlavičkovém souboru.
// Říká překladači, že někde je napsaná funkce fn, která vrací int a 
// to překladači stačí. Až linker si bude stěžovat, když tato funkce nikde
// nebude.
int fn(); 

void main() {
 fn();   // použijeme funkci, které chybí tělo, to vyhodí unresolved external
} 
... already defined in error_test.obj
Jak už chybová hláška napovídá, daný symbol se vyskytuje ve dvou zdrojových souborech a v obou má stejné jméno. Pokud se jedná o funkci, musí mít jedna z nich jiné jméno.
Pokud se snažíte používat jednu proměnnou z více zdrojových souborů a proto jste ji vložili do hlavičkového souboru, musíte to udělat trochu jinak. Proměnná musí být deklarovaná jen v jednom zdrojovém souboru, v ostatních na ní musí být pouze odkaz. Například pro objekt spravující vstup by to mohlo vypadat takto:
input.cpp:
 InputManager inputManager;   // toto si můžeme představit jako vytvoření místa v paměti

input.h:
 extern InputManager inputManager;  // Zde je klíčové slovo extern. Říká, že někde existuje 
                                    // proměnná inputManager, ale nevytváří nový symbol.

game.cpp:
 #include "input.h"
 // a můžeme používat inputManager
Vlákno se stejným problémem
... redefiniton
Tato chybová hláška říká, že daný symbol už překladač jednou viděl. To se může stát, když includujete jeden hlavičkový soubor vícekrát. Proto hlavičkové soubory obvykle vypadají takto:
#ifndef INPUT_H_INCLUDED
#define INPUT_H_INCLUDED
 ... obsah souboru
#endif
Tyto instrukce zamezí opakovanému vkládání hlavičkového souboru. Novější překladače podporují jednodušší příkaz
#pragma once


spousta chyb týkajících se kódu, který není váš
Pravděpodobně bude problém s pořadím includovaných souborů nebo bude syntaktická chyba někde před includovanáním hlavičkového souboru, ve kterém překladač hlásí chyby.