2. előadás
Statikus vagy dinamikus típusrendszer
Statikus
Statikus típusrendszer: fordítási időben meg tudja határozni a részkifejezések típusát
Dinamikus
Interpretált nyelvekre jellemző, hogy egy változó egymás után más típusú adatra is mutathat. Ezek a nyelvek dinamikut típusrendszerrel rendelkezik.
A helytelen típushasználatok jellemzően az erősen típusos nyelveknél okozhat hibát szemben a gyengén típusos nyelvekkel.
Feladat - Temperature conversion
String substitution (formázás)
%d: ~~szám~~ intédzser kiírás-
%s: String kiírás -
%c: Karakter
Első hibás megoldás
/*
* Convert Fahrenheit to Celsius
* between -100F and +400F by 100F
*/
#include <stdio.h>
int main()
{
int fahr;
for ( fahr = -100; fahr <= 400; fahr += 100 )
{
printf("Fahr = %d,\tCels = %d\n",fahr,5/9*(fahr-32));
}
return 0;
}
$ gcc -ansi -pedantic -W -Wall -std=c11 fahrenheit.c -o fahrenheit
$ ./fahrenheit
Fahr = -100, Cels = 0
Fahr = 0, Cels = 0
Fahr = 100, Cels = 0
Fahr = 200, Cels = 0
Fahr = 300, Cels = 0
Fahr = 400, Cels = 0
Error
Hiba oka: Automatikus típuskonverzió (az osztásban használt két konstans típusa int, így az eredmény is int.)
Javítás: A két konstans valamelyikének típuskényszerítése (az érték konverziója, vagy egyből megfelelő típusban megadva)
Második hibás megoldás
/*
* Convert Fahrenheit to Celsius
* between -100F and +400F by 100F
*/
#include <stdio.h>
int main()
{
//Változó deklaráció
int fahr;
//Ciklus
for ( fahr = -100; fahr <= 400; fahr += 100 )
{
//Kiírás (lásd: formázás)
printf("Fahr = %d,\tCels = %d\n",fahr,5./9.*(fahr-32));
}
return 0;
}
$ gcc -ansi -pedantic -W -Wall fahrenheit.c -o fahrenheit
fahrenheit.c: In function ‘main’:
fahrenheit.c:17:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘double’ [-Wformat=]
printf( "Fahr = %d,\tCels = %d\n", fahr, 5./9.*(fahr-32) );
^
$ ./fahrenheit
Fahr = -100, Cels = 913552376
Fahr = 0, Cels = -722576928
Fahr = 100, Cels = -722576928
Fahr = 200, Cels = -722576928
Fahr = 300, Cels = -722576928
Fahr = 400, Cels = -722576928
Hiba oka: A számítás helyes, hiszen az eredmény típusa double, azonban a kiíratáskor egészt várunk (TypeError).
Megoldás: Kiíratásnál a várt típus módosítása, vagy az eredmény típuskonverziója.
A C nyelvben paraméterátadáskor csak akkor történik konverzió, ha a hívott függvényt teljes paraméterlistával előzetesen deklaráljuk. A printf esetében a paraméterek feloldása futási időben történik.
Első helyes megoldás
/*
* Convert Fahrenheit to Celsius
* between -100F and +400F by 100F
*/
#include <stdio.h>
int main()
{
int fahr;
for ( fahr = -100; fahr <= 400; fahr += 100 )
{
printf("Fahr = %d,\tCels = %f\n",fahr,5./9.*(fahr-32));
}
return 0;
}
$ gcc -ansi -pedantic -W -Wall fahrenheit.c -o fahrenheit
$ ./fahrenheit
Fahr = -100, Cels = -73.333333
Fahr = 0, Cels = -17.777778
Fahr = 100, Cels = 37.777778
Fahr = 200, Cels = 93.333333
Fahr = 300, Cels = 148.888889
Fahr = 400, Cels = 204.444444
A megoldás helyes, azonban vannak potenciális refaktorálási lehetőségek.
A metódus szignatúrája double fahr2cels(double), ezért az int típusú aktuális paraméter lebegőpontossá konvertálva adódik át. A %7.2f formátum 7 karakter szélességben, 2 tizedesre kerekítve írja ki az eredményt.
Első refaktorálási iteráció
/*
* Convert Fahrenheit to Celsius
* between -100F and +400F by 100F
*/
#include <stdio.h>
double fahr2cels( double f)
{
return 5./9. * (f-32);
}
int main()
{
int fahr;
for ( fahr = -100; fahr <= 400; fahr += 100 )
{
printf("Fahr = %4d,\tCels = %7.2f\n",
fahr, fahr2cels(fahr));
}
return 0;
}
$ gcc -ansi -pedantic -W -Wall fahrenheit.c -o fahrenheit
$ ./fahrenheit
Fahr = -100, Cels = -73.33
Fahr = 0, Cels = -17.78
Fahr = 100, Cels = 37.78
Fahr = 200, Cels = 93.33
Fahr = 300, Cels = 148.89
Fahr = 400, Cels = 204.44
Az eredmény könnyebben kezelhető, azonban van még egy refaktorálási potenciál.
Használjunk előfordító direktívákat (
preprocessor directive) konstansok deffiniálására
Konstansok előfordított direktívákkal
/*
* Convert Fahrenheit to Celsius
* between -100F and +400F by 100F
*/
#include <stdio.h>
#define LOWER -100
#define UPPER 400
#define STEP 100
double fahr2cels( double f)
{
return 5./9. * (f-32);
}
int main()
{
int fahr;
for ( fahr = LOWER; fahr <= UPPER; fahr += STEP )
{
printf( "Fahr = %4d,\tCels = %7.2f\n",
fahr, fahr2cels(fahr) );
}
return 0;
}
Konstansok névvel ellátva
/*
* OK, with const
* Convert Fahrenheit to Celsius
* between -100F and +400F by 100F
*/
#include <stdio.h>
const int lower = -100;
const int upper = 400;
const int step = 100;
double fahr2cels( double f)
{
return 5./9. * (f-32);
}
int main()
{
int fahr;
for ( fahr = lower; fahr <= upper; fahr += step )
{
printf( "Fahr = %4d,\tCels = %7.2f\n",
fahr, fahr2cels(fahr) );
}
return 0;
}
A C programok szerkezete
Alapvető tokenek
/*
* my first C program <--- comment
*
*/
#include <stdio.h> //<---- preprocessor directvive
int main() // int <-- type name: keyword
// main <-- function name: identifier
// () <-- function call: operator
{ // { <-- block begin: separator
// printf <-- function name: identifier
// ( <-- function call: operator
printf("Hello world"); // "Hello world" <-- string literal, type char[12]
// ) <-- function call: operator
// ; <-- command-end separator
// return <-- keyword
return 0; // 0 <-- decimal int literal, type int
} // } <-- block end: separator
include
Relációs jelek (
<>) helyett idézőjelek (""): jelenlegi mappából tölt be, nem a szabványos helyről.
Szintaktikai elemek
- Kulcsszó (keyword)
- A nyelvben előre definiált jelentéssel bír
- Azonosító (identifier)
- Csak az adott kontextusban bír jelentéssel, jellemzően futási időben kap jelentést
- Szeparátor
- Literál
- Komment
- Fordítási időben ignorálásra kerül, erősen tájékoztató jellegű
Szintaktikus/Sin-patikus csapat!
Azonosítók
- betűvel kezdődnek (
_is betű) - betűk és számok
- TILOS kulcsszót használni
Megszokott konvenciók
camelCaseNotationCTypenamesStartsWithUpperCaseunder_score_notationorsnake_caseSTRING_HUNGARIAN_NOTATIONalso known as.. oops it got stolen
| Megnevezés | példa | típus | értéke |
|---|---|---|---|
| decimális egész | 25 | int | 25 |
| oktális egész | 031 | int | 25 |
| hexadecimális egész | 0x19 | int | 25 |
| hosszú egész | 12L | long int | 12 |
| C99 még hosszabb egész | 12LL | long long int | 12 |
| előjel nélüli egész | 12u | unsigned int | 12 |
Legtöbb nyelv kettes-komplemens használ
- Előjel nélküli egész szám (unsigned): csak pozitív számokat tud ábrázolni
- Előjeles egész szám (signed): negatív számokat is tud ábrázolni, de feleannyi értéket tud felvenni
C - Típusok
Escape karakterek
Karakterek, amiknek bevitele a szerkesztőbe nem lehetséges, vagy a fordító tokenként értelmezné.
Például:
\'->'\"->"\?->?\\->\\a-> bell\b-> backspace\f-> új oldal\n-> új sor\r-> soremelés\t-> horizontal tab\v-> vertical tab
Integer
sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
shortmin. 16 bitlongmin. 32 bitlong longmin. 64 bit
Fix és lebegőpontos számok (fix and floating point numbers)
Fix pontos: megadott bit számú tört rész

Levegőpontos számok: nincs fixen megadva a "tizedes" hely. Helyette normálalak-szerű leírás.
IEEE 754 (lásd: SzámRend)