Это действительный макрос в C? - PullRequest
1 голос
/ 08 сентября 2010

Если я использую макрос:

#define AND

следующим образом:

if(...)
{
...
}
elseANDif(...)
{
...
}

Какой вывод производит препроцессор?

Edit: Я намерен использовать:

#define TEST(params) if(...){...}else  

... в if (...) - сложное выражение с использованием параметров

... in {...} выполняет некоторые операции и не зависит от параметров

#define AND

TEST(x1) AND TEST(x2)
{
    //the code for the final else
}

И помогает ли И здесь или я могу обойтись без него?

Ответы [ 3 ]

9 голосов
/ 08 сентября 2010

Нет, это не сработает, как вы ожидаете.И вы можете проверить, что делает препроцессор, пропустив код через cpp.

eliben@eliben-desktop:~/temp$ cat z.c
#define AND

if(...)
{
    ...
}
elseANDif(...)
{
    ...
}

eliben@eliben-desktop:~/temp$ cpp z.c
# 1 "z.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "z.c"


if(...)
{
    ...
}
elseANDif(...)
{
    ...
}

Техническая причина заключается в том, что когда cpp расширяет макросы, он ищет маркер полного идентификаторасоответствие имени этого макроса.Т.е. в вашем случае он ищет идентификатор AND.Однако, когда он анализирует код, он не находит такой идентификатор.Он находит elseANDif, который является совершенно другим идентификатором.У него нет способа разбить elseANDif на составляющие, и это хорошо, потому что иначе макросы будут работать очень плохо.Представьте себе:

const int FUSIONDEBUG = 5;

Что бы это ни значило, в реальном C-коде это ужасно сломалось бы, поскольку в рабочем коде NDEBUG почти всегда определяется как пустой (Google означает, что означает NDEBUG).


Что касается вашего редактирования, лучший совет, который я могу вам дать по таким вопросам, это НЕ ДЕЛАЙТЕ ЭТОГО .(ab) Использование макросов, подобных этому, может показаться на первый взгляд, чтобы сделать код более читабельным, но в долгосрочной перспективе это делает его гораздо менее читабельным, с добавленной опасностью, что макросы сложно получить совершенно правильно и с определенной комбинацией токенов может взорватьплохо на вас.

Так что вы определенно можете обойтись как без AND, так и без TEST в целом.

2 голосов
/ 08 сентября 2010

Это:

#define TEST(condn) if(...){...}else

ерунда; что вы ожидаете от эллипсов (...)!?

пример использования, который вы дали, расширится до

if(...){...} else if(...){...}else
{
    //the code for the final else
}

что явная ерунда; где используется аргумент condn? В любом случае, независимо от того, что вы на самом деле предполагали, AND не оказывает никакого влияния, кроме фиктивной читабельности. Если вы пытаетесь изобрести новый язык, препроцессор C не способ сделать это. Я не вижу преимущества в том, чего вы пытаетесь достичь по сравнению с более простым кодом.

Если вы намеревались:

 #define TEST(condn) if(condn){/*some code*/}else

тогда как получается:

if(a==b){/*some code*/} else if(b==c){/*some code*/}else
{
    //the code for the final else
}

лучше чем:

if(a==b || b==c)
{
    /*some code*/
} 
else
{
    //the code for the final else
}

, где /*some code*/ не дублируется без необходимости?

Обратите внимание, что здесь единственное условие, объединенное в цепочку ||, эквивалентно вашим множественным условиям, объединенным в цепочку else if, поэтому даже если вы используете макрос TEST, нет необходимости использовать его таким образом, когда:

TEST( a==b || b==c)
{
    //the code for the final else
}

будет достаточно.

В лучшие времена макросы часто бывают необоснованными, но вы выбрали особенно яркий пример злоупотребления макросами! Рассмотрим, например, как вы можете отлаживать такой код в отладчике исходного уровня.

1 голос
/ 08 сентября 2010

Короткий ответ на ваш вопрос - «да». Вы, конечно, можете делать то, что вы предлагаете. Вот простой рабочий пример:

#include <stdio.h>

#define AND
#define TEST(params) if (!params) { printf(#params " was false\n"); } else 

int main(int argc, char ** argv)
{
    int param_1 = 1;
    int param_2 = 0;

    TEST(param_1) AND TEST(param_2)
    {
        printf("success!\n");
    }
}

После раскрытия макроса код будет выглядеть примерно так:

int main(int argc, char ** argv)
{
    int param_1 = 1;
    int param_2 = 0;

    if (!param_1) { printf("param_1 was false\n"); } else 
    if (!param_2) { printf("param_2 was false\n"); } else
    {
        printf("success!\n");
    }
}

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

int test_parameters(int params)
{
    if (!params) { printf("bad parameters"); return 0; }
    else { return 1; }
}

int main(int argc, char ** argv)
{
    int param_1 = 1;
    int param_2 = 0;

    if (test_parameters(param_1) && test_parameters(param_2))
    {
        printf("success!\n");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...