1

Téma: Kompilátor

Uvažuji o použití některé z variant SDS a tak si trochu testuji ten kompilátor. Je jasné, že při velikosti kompilátoru včetně grafického prostředí kolem 3MB nemohu čekat žádné zázraky při kontrole sytaxe, nicméně mě zaráží, že mohu napsat téměř všechno a kompilace dopadne dobře. Něco z toho asi vyleze (binární soubor), ale vůbec nevím, co takový program může provádět, respektive, jak kompilátor dokáže mé nesmysly zpracovat.
Například toto:

void main(void)
{
    aaa = 3;
    printf("Hello World %d!n", aaa, bbb);
    for (;;);
}

Mám tomu rozumět tak, že nedeklarované proměnné se automaticky vytvoří (s typem Int_32)?

Podobně mohu volat neexistující funkci:

ahoj();

Pokud je to tak, že kompilátor nesmysly prostě překočí, tak to odladím až za běhu (např. pomocí výpisu) a jsem ochoten to tak akceptovat. Holt si budu muset při složitějších konstrukcích ověřit sám, zda to tak jde, či ne.

2

Re: Kompilátor

Odpovím si sám, je tomu tak. Většinu chyb vyhodí program až po spuštění.

3

Re: Kompilátor

Ano, u FULL-C se provádí část kontroly v EXE, a zbytek až při běhu programu.
To co "projde" do SDS, jsou vždy nesyntaktické chyby - kontrola v EXE nepropustí dále nespustitelný program.

Ve Vašem příkladu, nedošlo k zapsání chybné syntaxe, "pouze" k použití nedeklarovaných proměnných nebo funkce. To je odchyceno v okamžiku, kde se provádění programu dostane na dané místo, a je to ohlášeno ve výpisu v SDS.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

4

Re: Kompilátor

Děkuji za odpověď, je mi to jasné.

Ještě bych měl dotaz k funkcím s proměnným počtem parametrů, tedy např. void test(int i, ...). Funkce se dá takto deklarovat i volat, ale nemám přístup k volitelným parametrům - něco jako va_arg makro. Vypisoval jsem si i obsah paměti kolem &i (zásobník?), ale není tam nic rozumného. Pokud to nejde, nevadí, udělám to jinak.

5

Re: Kompilátor

Ano, va_arg není v současné době pro vlastní kód implementováno, ještě to musím promyslet. Samozřejmě interní funkce s tím umí pracovat bez problému (jako příklad printf a podobné).

Co se původní otázky týká, tak doporučím obecně pro složitější programy použít FULL-C.
SDS-C je také široce používán, zase právě pro svou jednoduchost, nebo je-li tlak na nízkou cenu HW (levnější moduly SDS).
Pozn. Pro SDS-C doporučím aplikaci SDSCP ( https://github.com/MightyPork/sdscp ), která umí zpracovat "plný" C kód na SDS-C, respektive tento preprocesor umí zapsat funkce a kód, které SDS-C přímo nenabízí.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

6

Re: Kompilátor

Ještě další takový špek z jazyka C. Chtěl bych si zjednodušit volání následující funkce:

void test(char *buf, int len)
{
   ....
}

Pokud chci předat data jen o jednom znaku, kterým je literál, musím napřed buffer rezervovat, naplnit hodnotou a potom předat. Jako buffer může být jen proměnná, tedy:

#define ALPHA 16

char val = ALPHA;
test(&val, 1);

Přímo hodnotu ALPHA jako pamater funkci nepředám. Toto nefunguje:

#define ALPHA 16

test(&ALPHA, 1);

Našel jsem kdesi na netu makro PTR_TO, které se v běžném C dá použít:

#define ALPHA 16
#define PTR_TO(X) ((tmp = X),&tmp)

test(PTR_TO(ALPHA), 1);

Pro FULL-C je to už asi příliš složité, nicméně funguje mi kupodivu toto:

#define ALPHA 16
void * PTR_TO(int X) { return &X; }

test(PTR_TO(ALPHA), 1);

Funkci se opravdu předá hodnota konstanty ALPHA, je to však bezpečné? Neuvolní se lokální proměnná funkce PTR_TO dřív, než je použita přes ukazatel ve funkci test?

PS: Omlouvám se za všetečné dotazy, nicméně SDS mi učarovalo pro svou jednoduchost a zkouším, co z něj vytáhnu. Jsem zvyklý psát programy co nejúsporněji a pokud se mi podaří ze 20 řádků zdrojového kódu udělat 10, je to tak přehlednější i pro mě, když se k programu po čase vrátím.

7

Re: Kompilátor

To makro (a i ta funkce) PTR_TO je jen jiná, složitější forma zápisu použití & ... což by šlo definovat i jednodušeji jako
#define PTR_TO(X) (&(X))
ale - to tady není podstatné.

#define nevytváří proměnnou, je to pouze příkaz preprocesoru. Takže define &ALPHA nedává smysl, protože to je &16 a to nemá význam.
Naopak &val už význam má, neboť to vrátí ukazatel na místo v paměti, kde je proměnná val. A pokud se z toho ukazatele čte ("hvězdičkou") tak se vytáhne hodnota, která v tom paměťovém místě je zapsaná. Samozřejmě ukazatel je jiné čislo než zapsaná hodnota (leda v jediném případě je to stejné, pokud se tam náhodou zapíše shodná hodnota).

Poslední příkaz skutečně spekuluje na dočasný kontext, což není bezpečné. Výsledek uvedené funkce PTR_TO předá ukazatel na vstupní proměnnou "int X" která je na zásobníku (full-c si, po dobu provádění vnitřku volané funkce, dočasně uloží všechny vstupní proměnné na zásobník, takže &X skutečně v tu chvíli ukazuje na místo v paměti).
Po opuštění funkce ale už zásobník není platný, a bude brzy přepsán. Je obvykle jen náhodou, pokud dané místo ještě drží tu hodnotu co tam náhodou byla. Ale rozhodně na to nelze spoléhat.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

8

Re: Kompilátor

Tak jsem to samozřejmě myslel. Protože nejde předat adresu konstanty, musí se napřed její hodnota uložit do nějakého paměťového místa a získat jeho adresu. Chtěl jsem jen zjednodušit tento nutně dvouřádkový (dvoupříkazový) zápis. To dělá makro tak, že definuje dočasnou proměnnou tmp, na kterou pak odkazuje (chybí v něm definice typu tedy např. ((char tmp = (char)X), &tmp). Ale to je celkem jedno. Myslím, že v tomto případě to bude nejlepší udělat novou funkcí:

void testbyte(unsigned char x)
{
     test(&x, 1);
}

testbyte(ALPHA);

Ještě k tomu "nebezpečnému" volání funkce PTR_TO: mě spíš překvapuje, že se ta hodnota nepřepíše, protože uvolněný zásobník (hodnota ALPHA funkce PTR_TO) by se měl hned obsadit minimálně návratovou hodnotou funce PTR_TO, která se hned předává na zásobníku funkci test. Ale pochopil jsem, že zásobník je asi trochu jinak organizován než u klasického c, překládaného do strojového kódu (viz mé pokusy s proměnným počtem parametrů funkce), takže se tím dále nebudu zabývat. Ale dobré je to vědět.

Díky za ochotu zabývat se prkotinami.

9

Re: Kompilátor

absolonj napsal:

Ale pochopil jsem, že zásobník je asi trochu jinak organizován než u klasického c, překládaného do strojového kódu (viz mé pokusy s proměnným počtem parametrů funkce)

Ano přesně tak, prvky v zásobníku jsou obaleny informacemi o typu a jeho rozsahu, aby se (alespoň z větší části) zabránilo problémům typu buffer overflow (přístup za hranice pole) atd atd.
Takže zásobník je skutečně jinak organizován (a plnější) než při přímém překladu C kódu do asm a jeho vykonávání.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !