Личные директивы препроцессора - PullRequest
1 голос
/ 01 августа 2009

Будучи начинающим C , я бы хотел услышать, что разработчики Macro "определяют". Я думал о том, чтобы поместить их в заголовок, чтобы пропустить многословие, к которому я привык:

#define TS_ typedef struct {  
#define _TS(x) } x;

#define I(x)_ { int i; for ( i = 1; i <= x; i++ ) {  
#define _I } }

Могу ли я добавить \ n \ t и т. Д. В эти макросы? Как я хотел бы передать свой исходный код минус дополнительные включают в себя:

#define TS_ typedef struct {\n
#define _TS(x) } x;\n

#define I(x)_ { int i;\n\tfor ( i = 1; i <= x; i++ ) {\n 
#define _I \t}\n}\n

Будет ли это работать?

т.е.: Могу ли я использовать пропроцессор для замены моего исходного кода моим личным включением в форматированный источник без включения?

Ссылки на хорошие советы и рекомендации препроцессора также приветствуются.

Ответы [ 9 ]

16 голосов
/ 01 августа 2009

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

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

6 голосов
/ 01 августа 2009

Вы можете вставить пробел, экранируя символ новой строки

#define SOMETHING whatever\
This is part of the macro

Но, как говорили другие, это не очень хороший способ сделать это.

Было бы намного лучше заглянуть в макросы редактора, чтобы вы могли набрать ярлык и заставить редактор его развернуть.

4 голосов
/ 01 августа 2009

Вы идете по неверному пути. НЕ составляйте свои собственные директивы cpp, которые незнакомы другим - это сделает ваш код трудным для понимания и в какой-то момент поддержанным.

Попытайтесь найти хороший код C для чтения - хороший код C не использует эти вещи по уважительной причине.

3 голосов
/ 02 августа 2009

НЕ ДЕЛАЙТЕ ЭТОГО . Никто другой не сможет прочитать ваш код.

В качестве предостерегающего примера, посмотрите Оригинальные исходные тексты Стива Борна для оболочки Bourne , где он использовал макросы для написания кода в стиле пиджина Алголь.

1 голос
/ 01 августа 2009

Использование макросов C без необходимости может привести к боли, особенно если вы пытаетесь использовать его для расширения кода. Существуют варианты использования макросов C, но это не так.

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

1 голос
/ 01 августа 2009

Вы могли бы сделать это, но этот вид «личного языка» обычно не используется в мире Си, особенно если вы ожидаете, что кто-то еще будет читать ваш код в будущем.

Если вы делаете это только для себя, тогда не стесняйтесь #define делать все, что вы хотите, но ожидайте, что, как только вы начнете работать с кем-либо (или для кого-либо), вы не сможете продолжать использовать этот вид вещи.

0 голосов
/ 02 августа 2009

Всегда лучше передать переменную цикла в макрос. Блок - макрос имеет определенные проблемы с оптимизацией. Все компиляторы не гарантируют оптимизированный код obj для переменных «область видимости блока».

Например, следующий код, когда он скомпилирован без каких-либо опций оптимизации для gcc, печатает два отдельных адреса для & i. И один и тот же код при компиляции с опцией -O2 напечатает один и тот же адрес в обоих блоках.

{
    int i;
    printf("address of i in first block is %u\n", &i);
}
{
    int i;
    printf("address of i in sec block is %u\n", &i);
}

Присвоение имен языковым конструкциям делает код более читабельным. Мне нравится ваша идея, если вы сформулируете ее следующим образом.

#define GREEN 1
#define YELLOW 2
#define RED 3

# define NUM_COLORS 3

#define COLOR_ITER (color,i)           \
    for(i=GREEN, color = colors[i];    \
        i < NUM_COLORS;                \
        color = colors[++i])

int colors[3] = {GREEN, YELLOW, RED};

int
fun () {

    int j;
    color_t clr;

    COLOR_ITER(clr, j) {
        paint(clr);
    }

}

Здесь, независимо от того, как он написан, макрос COLOR_ITER по своему названию подразумевает, что вы циклически выполняете все доступные цвета и делаете «что-то» для каждого цвета. И это очень простой в использовании макрос.

И ваш вопрос

Могу ли я использовать пропроцессор для замены моего исходного кода своим личным включением в форматированный источник без включения?

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

0 голосов
/ 01 августа 2009

Я привык к элиф-конструкции Python, поэтому часто определяю следующее:

#define elif(test) else if(test)

Моя цель в этом состоит не в том, чтобы сократить ввод текста, а в том, чтобы логические отступы сохранялись при неизменной ширине кода (я не позволяю своему коду расширяться более чем на 80 символов). Я говорю это, потому что для меня это ...

if(...) ...
else if(...) ...
else ...

... должно быть ...

if(...)
{
    ...
}

else
    if(...)
    {
        ...
    }

    else
    {
        ...
    }

С моим макросом это становится:

if(...)
{
    ...
}

elif(...)
{
    ...
}

else
{
    ...
}
0 голосов
/ 01 августа 2009

В целом, я полностью согласен с другими респондентами, которые говорят, что вы не должны определять свои собственные макросы исключительно ради экономии текста. Запутывание не стоит. Кроме того, конкретные макросы, которые вы предлагаете, являются отвратительными. Однако в первом издании Страуструпа он делает что-то, что мне скорее нравится (иногда):

#define Kase break; case
...