Макросы C ++ #ifdef - PullRequest
       38

Макросы C ++ #ifdef

0 голосов
/ 21 февраля 2020
void testFunc();

int myval = 0;

int main()
{
    int a = 1;

    if (a > 0)
    {
        #define TEST1
        testFunc();
        #undef TEST1
    }

    int b = 2;
    if ( b > 0)
    {
        #define TEST2
        testFunc();
        #undef TEST2
    }

    std::cout << "val : " << myval << endl;

    getchar();

    return 0;
}


void testFunc()
{

#ifdef TEST1
#define HERE 1
#endif

#ifdef TEST2
#define HERE 2
#endif

#ifdef HERE
    myval = HERE;
#else
    myval = -1;
#endif

}

Как можно распечатать значение HERE, равное 1, когда testFun c () вызывается в первый раз, а затем вывести значение HERE, равное 2, когда оно вызывается во второй раз.

С текущим кодом, который у меня есть, печатается значение -1. ​​

Ответы [ 4 ]

6 голосов
/ 21 февраля 2020

Что вам не хватает, так это то, что директивы препроцессора вычисляются до времени компиляции.

Это означает, что, когда препроцессор анализирует ваш код, он:

  1. Устанавливает TEST1
  2. Unsets TEST1
  3. Sets TEST2
  4. Unsets TEST2
  5. Проверяет, определен ли TEST1 (не определен)
  6. Проверяет, определен ли TEST2 (он не)
  7. Проверяет, определен ли ЗДЕСЬ (это не так)

Это означает, что testFunc становится:

void testFunc() {
    myval = -1;
}

И затем, после При этой предварительной обработке ваш код компилируется.

Я бы подумал об использовании чего-то другого, кроме препроцессора, для достижения sh того, чего вы пытаетесь достичь.

2 голосов
/ 21 февраля 2020

То, как вы собираетесь это сделать, невозможно. Макросы оцениваются до компиляции. Он просто проанализирует документ сверху вниз и заменит текст в соответствии с макросами. Когда предварительная обработка достигает testFunc, оба значения TEST1 и TEST2 больше не определяются (вы #undef оба ранее в коде), поэтому вы получаете

void testFunc()
{
    myval = -1;
}

, что затем скомпилировано. Похоже, вы хотите создать что-то вроде функции шаблона? Возможно шаблоны реальных функций могут решить вашу проблему.

2 голосов
/ 21 февраля 2020

Как я могу напечатать значение HERE, равное 1, когда testFun c () вызывается впервые, а затем вывести значение HERE, равное 2, когда оно вызывается во второй раз.

Вот как выглядит ваша попытанная функция после предварительной обработки:

void testFunc()
{
    myval = -1;
}

Как видите, функция не принимает никакой формы ввода и всегда безоговорочно присваивает одно и то же значение глобальная переменная.

Вы не можете достичь того, что вы хотите, с помощью макросов.


Чтобы поведение печати различало значение в зависимости от того, сколько раз вы вызываете функцию, вы можете использовать функциональный объект вместо Функциональные объекты могут иметь внутреннее состояние:

auto testFunc = [HERE = 1]() mutable {
    return HERE++;
};
std::cout << testFunc(); // prints 1
std::cout << testFunc(); // prints 2
1 голос
/ 21 февраля 2020

Все операторы # называются директивами препроцессора. Это инструкции для компилятора. Вы хотите, чтобы фактически скомпилированный код поддерживал некоторое состояние среды выполнения программы.

Два способа сделать это можно sh, либо используя:

  1. Глобальная переменная
  2. Stati c переменная

В следующем примере показаны оба подхода. Каждая функция также имеет значение памяти, которое обновляется, чтобы запоминать, была ли эта функция когда-либо вызвана.

#include <iostream>

bool g_ran_already = false;

int first_different_global()
{
    if (!g_ran_already)
    {
        g_ran_already = true;
        return 1;
    }
    else
    {
        return 2;
    }
}

int first_different_static()
{
    static bool s_ran_already = false;

    if(!s_ran_already)
    {
        s_ran_already = true;
        return 1;
    }
    else
    {
        return 2;
    }
}

int main(int argc, char** argv)
{
    std::cout << "first_different_global() run 1: " << first_different_global() << "\n";
    std::cout << "first_different_global() run 2: " << first_different_global() << "\n";
    std::cout << "first_different_global() run 3: " << first_different_global() << "\n";
    std::cout << "first_different_static() run 1: " << first_different_static() << "\n";
    std::cout << "first_different_static() run 2: " << first_different_static() << "\n";
    std::cout << "first_different_static() run 3: " << first_different_static() << "\n";
}

Вывод:

first_different_global() run 1: 1
first_different_global() run 2: 2
first_different_global() run 3: 2
first_different_static() run 1: 1
first_different_static() run 2: 2
first_different_static() run 3: 2
...