Witam
Napisałem program w którym używam trochę makr #define xxx(Z) itd ; Czy jest taka możliwość aby zobaczyć jak wygląda kod po rozwinięciu tych makr ? Używam visual c++ 2008 express.
Witam
Napisałem program w którym używam trochę makr #define xxx(Z) itd ; Czy jest taka możliwość aby zobaczyć jak wygląda kod po rozwinięciu tych makr ? Używam visual c++ 2008 express.
#define square(a) (a)*(a)
int main() {
int x;
square(5);
}
dostajemy
# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.cpp"
int main() {
int x;
(5)*(5);
}
visual c++ 2008 express
Project -> blahblah Properties... -> Configuration Properties -> C/C++ -> Preprocessor -> Generate Preprocessed File na Without Line Numbers (/EP /P)
//quetz: A ODTAD DALEJ KLOCIMY SIE NAD WYZSZOSCIA NIZSZOSCI MAKR I GOTO:)
throw catch :P - to ma tą zaletę, że zagnieżdżoną pętlem można umieścić w funkcji i jeszcze bardziej uczynić kod czytelnym (z goto się tak nie da). Swoją drogą takie przypadki są bardzo bardzo rzadkie.
A w innych językach break działa niby jakoś inaczej?
Tja... Wyjątki do sterowania przepływem - nie wygląda to normalnie. Wyjątki służą, jak sama nazwa wskazuje, do obsługi sytuacji wyjątkowych.
W innych językach jest taki gotopodobny break, na przykład:
zuo:
while(cośtam)
{
while(inne cośtam)
{
if(zuezuo) break zuo;
}
}
//wylądujemy tutaj
Swoją drogą - porównanie goto do wulgaryzmów - fajna sprawa. Wulgaryzm właściwie użyty podbija dynamikę wypowiedzi - problemem jest nadużywanie, nie samo używanie.
Dokładnie :)
Swoją drogą ten break niewiele się różni od goto.
Shalom napisał(a)
@AklimX problem w tym ze używanie makr moze powodować wiele, trudnych do wyłapania, błędów. Tymbardziej w kodach osób początkujących. Ot choćby w podanej przez ciebie funkcji, co sie stanie jeśli "argumentem" makra będzie a++ ?
W makrze nie ma kontroli typów, więc mogą się tam dziać cuda, jesli ktoś nie do konca wie co robi.
Nie możesz rozwinąć makra rekurencyjnie.
Albo choćby przykład problemów z makrami który podaje Stroustrup:
#define MIN(a, b) a < b ? a : b
MIN(1, 3 < 2)
1 < 3 < 2 ? 1 : 3 < 2
(1 < 3) < 2 ? 1 : 3 < 2
#define MIN(a, b) (a)<(b)?(a):(b)
1+MIN(a,b)
1+(a)<b?(a):(b)
#define MIN(a, b) ((a)<(b)?(a):(b))
c = MIN(a++, b++)
c = ((a++)<(b++)?(a++):(b++))
Tak myślałem, że będzie flame. Wystarczy wspomnieć o makrach, zmiennych globalnych czy goto i od razu ktoś krzyczy. Czy ja kogoś zmuszam do ich używania? Czcze gadanie, że coś jest złe, bo można to źle wykorzystać... a nóż? a kij bejsbolowy?
A funkcję square napisałem bo akurat mi przyszła do głowy, nie dlatego, że uważam ją za wzór do naśladowania.
Zaczynając programowanie od języka C/C++ trzeba się liczyć z tym, że można postrzelić się w nogę (dość łatwo zresztą). Jak ktoś lubi spać spokojnie niech pisze w Haskellu (choć imo do przyjemnych on nie należy) albo chociaż w Javie.
Zgadzam się z tezą, że goto, makra, zminne globalne użyte w odpowiednim miejscu będą good, wszystko jest dla ludzi. Natomiast początkujący kategorycznie nie powinni ich używać. No może z wyjątkiem zmiennych globalnych, tych powinni używać jak najmniej, w ostateczności.
Przykład na sensowne użycie makr: piszemy kod cross-platform i chcemy nadać pewnym systemowym funkcjom wspólną nazwę. Z aliasu w postaci makra płyną jedynie korzyści.
Inny przykład: konstrukcja (deklaracja+inicjalizacja) tablicy pewnych rozbudowanych struktur. Zamiast całego wiersza zapełniając wszystkie pola stosowny zestaw makr skróci zapis a kod będzie czytelniejszy.
Przykład na goto: piszemy kod, który musi być maksymalnie wydajny (sterownik, system operacyjny). goto gdzieniegdzie na pewno się przyda.