A bc ezen implementációja sok bővítéssel rendelkezik a POSIX standardhoz képest. Parancssor opcióval megadható, hogy a program ezeknél figyelmeztessen, vagy dobja vissza őket. Ez a dokumentum az ezen feldolgozó által elfogadott nyelvet írja le. A kiterjesztések természetesen jelölésre kerülnek.
Négy speciális változó van, scale, ibase, obase, és last. A scale azt definiálja, hogy néhány művelet a tizdes pont után hány számjegyet használjon. A scale alapértelmezett értéke 0. Az ibase és az obase definiálja a bemeneti és a kimeneti számrendszer konverziót. Az alapértelmezett számrendszer mind a bemenetre, mind a kimenetre 10-es. A last (kiterjesztés) változóban az utolsó kiírt érték szerepel. Ez később kerül részletezésre. Ezeknek vátlozóknak lehet értéket adni, de kifejezésben is használhatóak.
Egy egyszerű kifejezés egy konstans. A bc a konstanst az ibase változóban megadott bemeneti számrendszer szerint decimális számmá konvertálja. (Kivétel a függvényeknél.) Az ibase érvényes értékei 2-től 16-ig terjednek. Ezen a határon túli értéket megadva az ibase változónak, a változó értéke 2 vagy 16 lesz. A bemenő számok a 0-9-ig és az A-F-ig terjedő karaktereket tartalmazhatják. (Megjegyzés: Nagybetűknek kell lenniük. A kisbetűk a változóknak vannak fenntartva.) Az egy számjegyű számoknak mindig a számjegy az értéke, az ibase változótól függetlenül (pl.: A = 10). A több számjegyű számoknál a bc az ibase-nél nagyobb számjegyeket bc - 1-re cseréli. Ezáltal, a FFF mindig a lehetó legnagyobb háromjegyű számot jelenti.
A teljes kifejezések hasonlóak a többi magas szintű nyelvben levőkhöz. Mivel csak egyetlen típusú szám van, nincs szabály a típusok keverésének kezelésére. Minden kifejezésnek van egy pontossága. Ez az eredeti számokból, az elvégzett műveletekból és még sok egyébből tevődik össze, az értéke a scale változóban található. Ezen változó legális értékei a 0-tól a C nyelvben egész számnak megadható legnagyobb értékig terjednek.
Itt következik a legalis kifejezések leírása, az "expr" a teljes kifejezésre, a "var" pedig egy egyszerű, vagy egy tömb változóra vonatkozik. Egy egyszerű változóra a
A relációs kifejezések speciális kifejezés fajták, amelyek mindig 0-t, vagy 1-et adnak vissza, 0-át, ha a reláció hamis, és 1-et, ha igaz. Ezek bármilyen legális kifejezésben megjelenhetnek. (A bc POSIX változatában, hogy a relációs kifejezések csak if, while és for utasításokban szerepelhetnek, illetve csak egy tesztelésük lehetséges.) A relációs operátorok a következők:
A boolean műveletek is legálisak. ( A POSIX bc-ben nincsenek boolean műveletek.) Minden boolean műveletnek az értéke 0, vagy 1 (hamis, vagy igaz), mint a relációs műveleteknél. A boolean műveletek a következőek:
A kifejezések precedenciája a következő (alacsonytól a magas felé):
Ez a precedencia úgy van megválasztva, hogy a POSIX bc alá programok is korrekten fussanak. Emiatt, a relációs és logikai operátorokat az értékadó operátoroknál néha szokatlan eredmény is kijöhet. Lásd a következő kifejezést:
A legtöbb C programozó ezt úgy értelmezi, hogy a "3 < 5" (az értéke 1) kerül az "a" változóba. A bc itt a következőt csinálja, hozzárendeli a 3-at az "a" változóhoz, majd a 3-at összehasonlítja az 5-tel. A legjobb, hogyha értékadó operátort használsz relációs, és logikai operátorokkal, akkor használsz zárójeleket.
Van néhány egyéb speciális kifejezés, amelyet még a bc nyújt. Ezek a felhasználó által definiálható függvények, és a standard függvények hívása. Ezek a következő alakban jelennek meg: name(fIparametersfB) A függvényekhez lásd még a felhasználó által definiált függvények fejezetet. A standard függvények a következőek:
A paraméterek számok, vagy tömbök lehetnek (kiterjesztés). A függvény definícójában nulla, vagy több paraméter definiálható, vesszővel elválasztva. A számok csak érték szerinti átadással, a tömbök csak cím szerinti átadással hívódnak meg. A tömböket a paraméterek között a "név[]" módon kell specifikálni. A függvényhívásnál a szám paraméterek teljes kifejezések lehetnek. A tömböknél ugyanaz a jelölés használandó, mint a definiáláskor. A nevesitett tömbök cím szerinti átadással kerülnek a függvényhez. Mivel a függvény definíciója dinamikus, a paraméterek száma és típusa csak a hívás pillanatában kerül ellenőrzésre. Ha ebben eltérés mutatkozik, egy futási-hiba váltódik ki. Futási-hiba váltódik ki akkor is, ha egy nem létező függvényt hívunk meg.
Az auto_list egy opcionális változó lista, amely "helyi" változókat tartalmazza. A szintaxisa: "auto név, ... ;". (A pontosvessző opcionális.) Minden név egy auto változó neve. Tömbök is definiálhatóak így, a szokásos módon. Ezek a változók a vermen kapnak helyet, a függvény belépése után. A változók ezután inicializálásra kerülnek nulla kezdőértékkel, és a függvény végrehajtása során használhatóak. Amikor a függvény kilép, ezeket a változókat eltávolítja a veremből, így az eredeti értékük helyreállítódik. A paraméterek is auto változók, amelyek a függvény meghívásakor kapják meg értéküket. Az auto változók különböznek a tradícionális helyi változóktól a következő dologban: ha A meghívja a B függvényt, B látja az A auto változóit, hacsak B-ben nincs ugyanezen néven is auto változó definiálva. Azon tény miatt, hogy az auto változók és a paraméterek egy vermen kapnak helyet, a bc kezeli a rekurzív függvényeket is.
A függvény törzse bc utasítások listája. Az utasításokat pontosvesszők, vagy újsorok választják el. A return utasítás hatására a függvény végrehajtása véget ér, és visszatér egy értékkel. Az első forma, a "return", 0-át ad vissza a hívónak, míg a második, "return ( kifejezés )", kiértékeli a kifejezést, és az eredményt adja vissza. A függvény végén, ha mást nem írunk ki, mindig van egy "return (0)", ez megkímél attól, hogy explicite ki kelljen írni a return utasítást.
A függvényeknél megváltozik az ibase változó használata is. A függvény törzsében szereplő minden konstans, a függvény hívásakor használatos ibase alapján konvertálódik. Ha az ibase-t megváltoztatjuk egy függvényben, annak nem lesz hatása, kivéve a read standard függvényt, amely mindig az ibase aktuális értékét használja a számok konvertálásához.
Az itt következő példában a matematikai könyvtárban található hatvány függvény definícióját mutatjuk be. A függvény POSIX bc nyelven íródott.
/* Kihasználja a következó tényt: e^x = (e^(x/2))^2. Mikor az x elég kicsi, a következő sort használjuk: e^x = 1 + x + x^2/2! + x^3/3! + ... */
define e(x) { auto a, d, e, f, i, m, v, z
/* Ellenőrzi az x előjelét. */ if (x<0) { m = 1 x = -x }
/* Elófeltétel. */ z = scale; scale = 4 + z + .44*x; while (x > 1) { f += 1; x /= 2; }
/* Inicializálja a változókat. */ v = 1+x a = x d = 1
for (i=2; 1; i++) { e = (a *= x) / (d *= i) if (e == 0) { if (f>0) while (f--) v = v*v; scale = z if (m) return (1/v); return (v/1); } v += e } }
A következő kód a bc kiterjesztett szolgáltatásait használja, egy egyszerű csekkfüzet egyenleg kiszámolására. Legjobb, ha ezt a programot fájlba lementjük, hogy többször is használhassuk anélkül, hogy újra be kelljen gépelni.
print "Kezdeti egyenleg? "; bal = read() bal /= 1 print "\n" while (1) { "jelenlegi egyenleg = "; bal "tranzakció? "; trans = read() if (trans == 0) break; bal -= trans bal /= 1 } quit
A következő függvény a faktoriális rekurzív definíciója.
A különbségek legfőbb forrásai a kiterjesztések, hol egy szolgáltatás lett kiterjesztve, hogy több lehetősége legyen, hol pedig új szolgáltatás lett létrehozva. A következó lista megmutatja a különbségeket és a kiterjesztéseket.
Philip A. Nelson phil@cs.wwu.edu