Глава 4. Оператори

Съдържание

Предпроцесор

Предпроцесор

Този раздел не е довършен.

Използването на предпроцесора има този недостатък, че компилаторът не работи директно с това, което сме написали и затова:

  1. издава странни съобщения за грешка;

  2. не проверява синтактичната коректност на цялата програма, а само на част;

  3. не проверява типовете при макроси.

Вместо

#define pi 3.1415926
        

е по-добре да се използва

const float pi = 3.1415926;
        

Така компилаторът ще знае и типът, от който искаме да бъде константата.

Вместо

#define BLACK 0
#define WHITE 255
#define RED 34
#define BLUE 87
#define GREEN 148
        

е по-добре да се използва[14]

enum colors {black=0, red, blue, gree, white=255};
        

Друго предимство е, че при трасиране ще виждаме символни стойности като red и green, вместо непонятни числа.

Подобно, вместо да се използват параметризирани макроси, е по-добре да използваме функции. При тях е гарантирано, че аргументите ще се изчисляват само веднъж. Ако това е важно за ефективността на програмата, те може да бъдат обявени като inline, при което компилаторът ще генерира идентичен код, но ще може да извърши и по-пълен семантичен контрол върху програмата. Например вместо

#define abs(x) (((x)>=0)?(x):(-x))
        

е по-добре да използваме

inline int abs(int x) {
    return x >= 0 ? x : -x;
}
        

Функцията abs ще работи коректно при използване на abs(i++), докато макросът ще увеличи аргумента двукратно.

Кога използваме условна компилация (#if, #ifdef, #ifndef)?

  • За поддържане на различни варианти на програмата (тестов/окончателен, различни числени методи Нютон/хорди, когато с тестове ще се установи кой вариант е най-удачният). Тук от всички варианти в крайна сметка се пуска само един.

  • За нагаждане към конкретната ОС и процесор

Когато е възможно, е по-добре да се използва обикновен условен оператор вместо условна компилация, защото така се проверява семантичната коректност на цялата програма, а не само на част.

Така например вместо

#ifdef HAS_FOO
...
#else
...
#endif
        

е по-добре да използваме

if (HAS_FOO)
    ...
else
    ...
        

Модерните компилатори и в двата случая ще генерират идентичен код.



[14] В този пример е показано, че ако точната стойност на някои от константите не е важна, може и да не я уточняваме.