• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

makra, programowanie w C

Object Storage Arubacloud
0 głosów
515 wizyt
pytanie zadane 23 listopada 2019 w C i C++ przez Ola Piątek Nowicjusz (240 p.)
#define MAX1 10
#define MAX2 15
#define MAX3 MAX1 - MAX2

 

int b = MAX1 - MAX3;

 

Dlaczego b wynosi  -15 skoro 10-(10-15)=15??

2 odpowiedzi

+2 głosów
odpowiedź 23 listopada 2019 przez tkz Nałogowiec (42,000 p.)
komentarz 23 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Tak. Najlepiej używać nawiasów w definowaniu makr. A poza tym można użyć funkcji, nawet w C.
komentarz 23 listopada 2019 przez tkz Nałogowiec (42,000 p.)
Najlepiej nie używać makr w ogóle... Funkcje, albo const z static był by lepszym wyborem.
komentarz 23 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Zachowajmy rozsądek, do zefiniowania kilku stałych makra są dobre, wygodne i bezpieczne. Ale jak ktoś robi w makrodefinicjach jakieś operacje, to ryzykuje błędy bardziej niż gdyby używał szablonów, stałych itd.
komentarz 24 listopada 2019 przez mokrowski Mędrzec (155,460 p.)

Najlepiej nie używać makr w ogóle... Funkcje, albo const z static był by lepszym wyborem.

W C nie masz wyjścia. Makra to jedyne czego możesz użyć by dostarczyć do języka mechanizmy metaprogramowania. Atrybut (jakikolwiek: const/static lub kombinacja), niestety buduje zajętość pamięci programu a makro nie. Stąd w C dla embedded, tak częste użycie makr bo oszczędza się w ten sposób flash MCU.

Zachowajmy rozsądek, do zefiniowania kilku stałych makra są dobre, wygodne i bezpieczne.

Hmm.. IMHO. Ani makra nie są dobre ani bezpieczne :) Tylko że dla C nie ma wyjścia a dla C++ oczywiście są lepsze rozwiązania i tu (dla C++) można zastąpić je czy wyrażeniami constexpr czy szablonami.

Poza tym każdy kompilator ma możliwość zatrzymania kompilacji na etapie rozwijania makr i wtedy będzie wiadomo co się stało. Błędny kod:

#include <stdio.h>

#define ADD(x, y) x + y
#define SHOW_TABLE(table, size) \
    for(size_t i = 0; i < size; ++i) { \
        printf("%d ", table[i]); \
    }

int main(void) {
    int tab[] = {10, 20, 30};
    printf("2 * (2 + 2) = %d\n", 2 * ADD(2, 2));
    SHOW_TABLE(tab, 3);
    putchar('\n');
    return 0;
}

Wywołanie z zatrzymaniem na rozwinięciu makr (dla gcc, icc, clang):

gcc `-E -P -o errors.i errors.c

Rozwinięty kod:

// ....
int main(void) {
    int tab[] = {10, 20, 30};
    printf("2 * (2 + 2) = %d\n", 2 * 2 + 2);
    for(size_t i = 0; i < 3; ++i) { printf("%d ", tab[i]); };
    putchar('\n');
    return 0;

I już widać co się stało :)

Oczywiście kompilator Visual Studio także ma odpowiednie przełączniki...

komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
>> Zachowajmy rozsądek, do zefiniowania kilku stałych makra są
>> dobre, wygodne i bezpieczne.

> Hmm.. IMHO. Ani makra nie są dobre ani bezpieczne :)

Ale ja pisałem coś jeszcze na dole na ten temat :)

Makro w postaci jednej stałej, np.:
#define IP ("222.33.33.33")
jak może zwiększać ryzyko popełnienia błędu przez programistę? Będę wdzięczny za pokazanie przykładowego błędu (ktory by nie wystąpił jakby użyć constexpr, funkcji static inline, itd).
komentarz 24 listopada 2019 przez tkz Nałogowiec (42,000 p.)
Makra nie mają przestrzeni nazw, więc może to kolidować z czymś innym.
komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Ale brak przestrzeni nazw, gdy używa się makr rozsądnie, z umiarem, chyba nie powoduje czesto jakiś błędów? Przynajmniej ja nie miałem. Ja miałem tylko trudne błędy do wykrycia, gdy źle użyłem nawiasów w makrach. Poza tym makra lubię, ale oczywiscie nie wtedy gdy makra stanowia jakiś istotny procent części całego programu.
komentarz 24 listopada 2019 przez tkz Nałogowiec (42,000 p.)
Makra to tylko część języka, wszystko używane z głową spełnia swoje zadanie. Warto tylko wiedzieć o ograniczeniach.
komentarz 24 listopada 2019 przez mokrowski Mędrzec (155,460 p.)

@mmarszik, a to IP, to z jakiej klasy sieci jest? O... zobacz... błąd który można usunąć przez wyrażenie constexp.

komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Nie rozumiem. Jaki błąd, dlaczego rozmawiamy o klasie sieci?
komentarz 24 listopada 2019 przez mokrowski Mędrzec (155,460 p.)
Nie wszystkie kombinacje wartości w  IPv4, są poprawnym adresem. A jak nie wiesz czym są klasy, to wiedzę warto uzupełnić.
komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Jak odpowiadasz w takim tonie, to pozwól że i ja odpowiem w takim: Jak nie wiesz że makra można walidować, to nie udzielaj się w rozmowach.
komentarz 24 listopada 2019 przez mokrowski Mędrzec (155,460 p.)
Ja myślę że nie warto być "ponurym piastunem własnej godności";) Zapytałeś o przykład, dostałeś odpowiedz i ponownie (jak już wiele razy to miało miejsce), albo naprawdę nie rozumiesz albo nie chcesz pogłębić wiedzy. Ja wiem że makra można walidować i wiem gdzie mają zastosowanie. To nawet wynika z tego wątku bo pokazałem (częściowo) jak :> Brawo więc za celność argumentów i spostrzegawczość;)

Nie. Nie mam ochoty na dyskusje na takim poziomie na jakim chcesz ją poprowadzić. Także ze względu na jej "głębię merytoryczną".

Powodzenia...
komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Dziwny jesteś, pamiętasz moje wątki, a zapomniałeś tak głęboko że używałem klas iż musiałeś mnie namawaić do ich nauki.
komentarz 24 listopada 2019 przez mokrowski Mędrzec (155,460 p.)
Tak... klasy sieci.. ja nie wiem co mam powiedzieć... No to może link "Padawanie" https://www.moje-ip.eu/klasy-adresow-protokolu-ip
komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Co mają klasy sieci wspólnego z brakiem błędów z powodu makr które są używane z głową i do definiowana stałych?
komentarz 24 listopada 2019 przez tkz Nałogowiec (42,000 p.)
Nie wiem poco jest ta wymiana zdań. Nie wiem również poco używane są argumenty ad hominem. Nie lepiej było by uzyskać rację powołując się na dokumentację lub kod potwierdzający postawioną tezę?
komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Było by lepiej, a nawet wiele leiej, już pisałem, że byśmy mogli się obaj od siebie wiele nauczyć. Ale jak ktoś mi każe się uczyć klas, to ja mu każe się uczyć pisania funkcji.
komentarz 24 listopada 2019 przez mokrowski Mędrzec (155,460 p.)

Jedno wystarczy...

http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines i wyszukać wystąpienie słowa macro.

komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)

Gdzie na tamtej stronie są przykłady o jakich ja pisałęm czyli przykłady użycia makr z głową? Bo chyba nie ten?

// webcolors.h (third party header)
#define RED   0xFF0000
#define GREEN 0x00FF00
#define BLUE  0x0000FF

// productinfo.h
// The following define product subtypes based on color
#define RED    0
#define PURPLE 1
#define BLUE   2

 

Poza tym kompilatory rzucają warningi że makro zostało przedefiniowane.

 

 

 

komentarz 24 listopada 2019 przez mmarszik Mądrala (7,390 p.)

Jak ktoś sobie zdefiniuje w pliku cpp przykładowe makro:

#define PI 3.14

To nie widzę jakiś szczególnych zagrożeń. Pchanie czegoś takiego do plików nagłówkowych w dużym programie który korzysta z dużej ilości nagłówków (w tym z zewnętrznych bibliotek) - owszem niesie z sobą zagrozenia. Ale kompilator krzyknie że makra są nadpisywana, tego typu błędy są w miarę łatwe do wykrycia.

 

+1 głos
odpowiedź 23 listopada 2019 przez Dorion300 Szeryf (90,250 p.)
edycja 24 listopada 2019 przez Dorion300
Nie podany został żaden nawias, a więc ostatecznie po operacji preprocesora masz takie coś:

int b = 10 - 10 - 15.

Można powiedzieć że Preprocesor tak jakby wkleja dosłownie zdefiniowaną wartość do kodu.
komentarz 23 listopada 2019 przez Eryk Andrzejewski Mędrzec (164,260 p.)
Nie dla każdego musi być to od razu oczywiste.
komentarz 23 listopada 2019 przez Dorion300 Szeryf (90,250 p.)
@Eryk  Jeśli moim wpisem kogoś uraziłem to przepraszam, nie taki był cel.

Przeczytałem dokładniej i poprawiłem aby brzmiało to bardziej przyjaźniej.
komentarz 23 listopada 2019 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Nie sądzę, żebyś kogoś uraził, tylko zaznaczyłem że nie dla każdego musi być oczywisty taki niuans działania preprocesora w C wink

Podobne pytania

0 głosów
1 odpowiedź 605 wizyt
pytanie zadane 14 maja 2020 w C i C++ przez Altair Nowicjusz (140 p.)
+1 głos
1 odpowiedź 547 wizyt
pytanie zadane 14 czerwca 2018 w C i C++ przez Mithriandil Początkujący (250 p.)
0 głosów
2 odpowiedzi 152 wizyt
pytanie zadane 24 maja 2017 w C i C++ przez Adam Olesiak Gaduła (3,290 p.)

92,536 zapytań

141,376 odpowiedzi

319,449 komentarzy

61,920 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...