jezc w08 makro make

background image

© 2012
Grzegorz Łukawski & Maciej Lasota

Politechnika Świętokrzyska w Kielcach

Standardowe wejście i wyjście,

preprocesor, stałe,

makrodefinicje, make.

Programowanie

w języku C

comm

background image

int

znak = getc(stdin);

fprintf(stdout,

"Tekst"

);

fgets(str, 32, stdin);

Standardowe wejście i wyjście

stdin

Standardowe wejście, domyślnie klawiatura.

stdout

Standardowe wyjście, domyślnie ekran (konsola).

stderr

Standardowe wyjście błędów, ekran (konsola).

Standardowe wejście i wyjście każdego programu można zastąpić
dowolnym plikiem:

./program <we.txt
./program >wy.txt
./program <we.txt >wy.txt
./program >>wyniki.txt

background image

Standardowe wejście i wyjście – potoki

Wejścia i wyjścia różnych programów można ze sobą łączyć z użyciem
tzw. potoków:

ls | ./program
./program | more
ls -l | wc | cat | more

background image

Polecenia systemowe i programy

system(

"polecenie i argumenty"

);

system(

"ls -l >>spis.txt"

);

system(

"inny_program"

);

system(

"C:\\programy\\wget.exe"

);

background image

Preprocesor to część kompilatora języka C zajmująca się
wstępnym przetwarzaniem kodu źródłowego.

Działaniem preprocesora steruje się z pomocą dyrektyw
preprocesora
(słowa kluczowe zaczynające się od znaku #).

Preprocesor

background image

Stałe symboliczne

Przyjęło się, że nazwy stałych symbolicznych zawsze są pisane wielkimi
literami.

#define

ILOSC

5

#define

NAZWA

”Moj program wersja 1”

#define

PI

3.1415

#define

PI2

2*PI

#define

ILE

32

// ...

int

tablica[ ILE ];

memset(tablica, 0, ILE *

sizeof

(

int

));

puts( NAZWA );

background image

W porównaniu do stałych symbolicznych mają dwie zalety:

1) można utworzyć do nich wskaźnik,
2) ich stosowanie nie powoduje zwielokrotnienia danych w kodzie

wynikowym.

Zmienne o ustalonej wartości

Są to zmienne, których wartości nie wolno zmienić – jeśli system
operacyjny na to pozwala, mogą znaleźć się w obszarze pamięci tylko do
odczytu.

const

int

Ilosc = 5;

const

char

*Nazwa = ”Moj program wersja 2”;

background image

Definicja typów z pomocą dyrektywy #define

#define

ULONG

unsigned

long

int

#define

BYTE

char

ULONG licznik = 100;
BYTE dane[16];

background image

Kompilacja warunkowa (1)

#define

DEBUGOWANIE 1

// ...

#if

DEBUGOWANIE==1

// Czy wartość 1?

printf(

"** n=%d, x=%d, suma=%f\n"

,n,x,suma);

if

(wskaznik==NULL)

printf(

"** Brak wskaźnika!\n"

);

#endif

// Koniec bloku

background image

#define

WINDOWZ 1

// ...

#if

WINDOWZ==1

char

*sciezka =

"C:\\dane\\plik.txt"

;

#else

char

*sciezka =

"~/dane/plik.txt"

;

#endif

Kompilacja warunkowa (2)

background image

#define

LICZ 10000

#if

LICZ<256

unsigned

char

licznik = LICZ;

#elif

LICZ<65536

unsigned

short

licznik = LICZ;

#else

unsigned

long

licznik = LICZ;

#endif

Kompilacja warunkowa (3)

background image

Typ wyliczeniowy

Typ wyliczeniowy (enum) służy do tworzenia zmiennych (typów)
zawierających tylko wybrane z góry ustalone wartości.

enum

Nazwa {W1, W2, WN};

enum

Kierunek {GORA, DOL, LEWO, PRAWO};

enum

Kierunek kierunek = GORA;

void

przesun(

enum

Kierunek kier,

int

x,

int

y) {

// ...

}

W rzeczywistości wartości typu wyliczeniowego przechowywane są jako
liczby typu int.

background image

Typ wyliczeniowy

Domyślnie przypisywane są kolejne wartości począwszy od zera, można to
zmienić w momencie deklaracji:

enum

Kierunek {GORA=10, DOL, LEWO, PRAWO};

printf(

"%d\n"

, GORA);

// 10

printf(

"%d\n"

, DOL);

// 11

background image

enum

Kierunek {GORA=10, DOL=10, LEWO=5, PRAWO=3};

enum

Kierunek kierunek = GORA;

// Przypisanie nieistniejącej stałej!

kierunek = (

enum

Kierunek)7;

Typ wyliczeniowy

background image

Makra tym różnią się od funkcji, że w miejscach wywołania makrodefinicji
wstawiany jest kod do niej przypisany (realizuje to preprocesor)*.

* Podobnie do makr zachowują się funkcje poprzedzone słowem „inline” (C99, C++).

Makrodefinicje

Makrodefinicje to sekwencje instrukcji deklarowane z pomocą operatora
#define. Mogą „udawać” funkcje wyposażone w opcjonalne argumenty
(bez typów danych):

#define

nazwa

instrukcje

#define

nazwa

(parametry)

instrukcje

background image

Makrodefinicje – przykłady

#define

DrukLinie

printf(

"-------------\n"

)

#define

DrukLiczbe(n)

printf(

"Liczba = %ld\n"

, n)

#define

Zeruj(x)

memset(&x, 0,

sizeof

(x))

// Makro złożone z wielu wierszy:

#define

DrukZnaki(z, n)

for

(i=0;i < n;i++) {\

if

(i) putchar(

','

);\

putchar(z);\

}

background image

#define

SwapInts(x,y)

{

int

z; z=y; y=x; x=z;}

Makrodefinicje – zastosowania

Makrodefinicje mogą zmieniać wartości zmiennych podanych jako
argumenty bez użycia wskaźnika, np.:

int

srednia(

int

x1,

int

x2,

int

x3,

int

x4) {...}

#define

srednia2(a, b)

srednia(a, a, b, b)

#define

getchar()

getc(stdin)

Pozwalają tworzyć nowe wersje już istniejących funkcji, np.:

background image

Dyrektywa #undef

Dyrektywa #undef unieważnia definicję stałej lub makrodefinicji – od
momentu jej wystąpienia w pliku źródłowym dana stała/makro przestaje
istnieć:

#undef

identyfikator

background image

W przypadku dużych programów kod źródłowy zaleca się podzielić na kilka
oddzielnych plików ".c".

Dla każdego pliku źródłowego można utworzyć tzw. plik nagłówkowy ".h",
w którym znajdą się definicje typów, stałych oraz prototypy funkcji
i danych udostępnianych do innych „modułów”.

Podział programu na moduły

UWAGA!
Tylko w jednym pliku źródłowym programu może znaleźć się jedna
funkcja main (więcej jeżeli występuje w bloku kompilacji warunkowej)!

background image

// main.c

#include

<...>

#include

"main.h"

#include

"wewy.h"

#include

"baza.h"

void

zeruj(

struct

towar *t) {

memset(t, 0,

sizeof

(

struct

towar));

}

int

main() {

struct

towar tow;

int

numer;

// Losowanie numeru towaru:

srand(time(NULL));

numer = rand() % ILET;

// Wypełnienie struktury:

zeruj(&tow);

strcpy(tow.nazwa, baza_towary[ numer ]);

tow.cena = baza_ceny[ numer ];

// Wyświetlenie i koniec:

wyswietl_dane(&tow);

return

0;

}

// main.h

#define

ILEZ 32

struct

towar {

char

nazwa[ILEZ];

float

cena;

};

void

zeruj(

struct

towar *t);

background image

// wewy.c

#include

<stdlib.h>

#include

<stdio.h>

#include

"main.h"

#include

"wewy.h"

void

wczytaj_tekst(

char

*t) {

fgets(t, ILEZ-1, stdin);

}

void

wyswietl_tekst(

char

*t) {

puts(t);

}

void

wczytaj_dane(

struct

towar *t) {

wczytaj_tekst(t->nazwa);

scanf(

"%f"

, &t->cena);

}

void

wyswietl_dane(

struct

towar *t) {

wyswietl_tekst(t->nazwa);

printf(

"CENA = %.2f\n"

, t->cena);

}

// wewy.h

void

wczytaj_dane(

struct

towar *t);

void

wyswietl_dane(

struct

towar *t);

background image

// baza.c

#include

"baza.h"

char

*baza_towary[ILET] = {

"Monitor Yumo 19"

,

"Monitor Yumo 22"

,

"Plyta DVD-R Cedek"

,

"Plyta CD-R Cedek"

,

"Klawiatura Baton-Ergo"

,

"Klawiatura Baton-Economy"

,

"Myszka Gryzon-Ergo"

,

"Dysk HDD Traktor 2TB"

,

"Plyta glowna Zimny-Lut Turbo"

,

"Karta graf. Pixeloza Turbo 1GB"

,

"Karta graf. Pixeloza Silent 2GB"

,

"Pamiec DDR3 Skleroza 2x1GB"

,

"Pamiec DDR3 Skleroza 4GB"

,

"Pendrive Forget-it 16GB"

,

"Obudowa Blaszak Tunafisza BLUE"

,

"Zasilacz Wyjec 300W"

};

float

baza_ceny[ILET] = {

199.99, 299.99, 2, 1, 99.99, 49.99, 19.99, 1000,

301, 999.99, 199.99, 99.99, 199.99, 19.99, 100, 50

};

// baza.h

#define

ILET 16

extern

float

baza_ceny[ILET];

extern

char

*baza_towary[ILET];

background image

W plikach nagłówkowych (*.h) można umieszczać tylko i wyłącznie treść nie
generującą żadnego kodu ani zmiennych
(prowadzi to do błędów
kompilacji). Dozwolone są między innymi:

definicje typów strukturalnych (struct);

definicje nowych typów danych (typedef);

stałe symboliczne (#define);

definicje zmiennych które mają być widoczne na zewnątrz
poprzedzone słowem extern;

prototypy funkcji udostępnionych na zewnątrz;

makrodefinicje;

funkcje typu inline (C99, C++).

Zawartość plików nagłówkowych

background image

Pliki nagłówkowe i kompilacja warunkowa

#ifdef STALA

Jeżeli STALA istnieje, wiersze poniżej aż do dyrektywy
#endif (lub podobnej) zostaną włączone do programu.

#ifndef STALA Jeżeli STALA nie istnieje, wiersze poniżej aż do

dyrektywy #endif (lub podobnej) zostaną włączone do
programu.

background image

// baza.h

#ifndef

MOJA_XYZ_BAZA_H

#define

MOJA_XYZ_BAZA_H

#define

ILET

16

extern

float

baza_ceny[ILET];

extern

char

*baza_towary[ILET];

#endif

// MOJA_XYZ_BAZA_H

Pliki nagłówkowe i kompilacja warunkowa

background image

gcc -c

main.c

(Powstanie plik main.o)

gcc -c

wewy.c

(Powstanie plik wewy.o)

gcc -c

baza.c

(Powstanie plik baza.o)

gcc

main.o wewy.o baza.o

-o

programik

Kompilacja programu złożonego z wielu plików źródłowych

background image

Kompilacja programu złożonego z wielu plików źródłowych

main.c

wewy.c

baza.c

main.o

wewy.o

baza.o

programik

stdio...

1) kompilacja x3

2) łączenie (konsolidacja, linkowanie)

background image

make

Program „make” to narzędzie wspomagające kompilację i linkowanie
złożonych

programów

napisanych

w

różnych

językach

programowania.

Narzędzie automatycznie (na podstawie czasów modyfikacji plików)
wykonuje tylko niezbędne kroki kompilacji i linkowania prowadzące
do utworzenia nowej wersji pliku wykonywalnego*.

*Sposób kompilacji i budowania programów w kompilatorach wyposażonych w interfejs IDE
(np. Visual Studio, Code::Blocks) wzorowany jest na działaniu narzędzia „make”.

background image

Makefile

Sposób postępowania prowadzący do skompilowania programu
powinien być zapisany pliku tekstowym o nazwie „makefile” lub
„Makefile”, umieszczonym w katalogu razem z plikami źródłowymi*.

Skompilowanie programu, w najprostszym przypadku, polega na
wywołaniu programu make z wiersza poleceń, bez parametrów.

* Plik dla programu make może mieć dowolną nazwę, ale wtedy trzeba ją przekazać
z pomocą dodatkowej opcji „-f”.

background image

cmodular.exe

: main.o wewy.o baza.o

gcc main.o wewy.o baza.o -o cmodular

main.o

: main.c main.h wewy.h baza.h

gcc -c main.c

wewy.o

: wewy.c wewy.h main.h

gcc -c wewy.c

baza.o

: baza.c baza.h

gcc -c baza.c

Makefile (Windows)

UWAGA!
Przed poleceniem do wykonania (drugi wiersz każdej reguły) musi
znaleźć się znak tabulacji (kod ASCII = 8).

background image

Automatyczne tworzenie reguł do pliku makefile

gcc -MM main.c

main.o: main.c main.h wewy.h baza.h

gcc -MM wewy.c

wewy.o: wewy.c main.h wewy.h

gcc -MM baza.c

baza.o: baza.c baza.h


Document Outline


Wyszukiwarka

Podobne podstrony:
jezc w08 makro make
W08 Patofizjologia zaburzeń gospodarki węglowodanowej
7 Mikro i makro elementy naszej diety
MAKRO 5
wyk makro 12 dok
w08
wykład makro 4
wyklad makro 14 wymiana
Podst wskazniki makro dla Polsk Nieznany
Makro cw Czerniak id 277438
makro pojecia2
makro wyklady
EVWL Makro Vorlesung4

więcej podobnych podstron