2013-09-20 4 views
0

Как и следующие коды исполнения (коды одинаковы, за исключением запятой во второй строке)Неожиданное поведение макросов в C

Этот код, как ожидается, выполнить и делает так же.

#include<stdio.h> 
#define SWAP(a, b) int t; t=a, a=b, b=t //note here is no semi-colon at the end 
int main() 
{ 
    int a=10, b=12; 
    SWAP(a, b); 
    printf("a = %d, b = %d\n", a, b); 
    return 0; 
} 

Но следующий не ожидается работать как SWAP(a, b) будет заменен int t; t=a, a=b, b=t;; .so два с запятой должен произвести ошибку !!!

#include<stdio.h> 
#define SWAP(a, b) int t; t=a, a=b, b=t; //note the semi-colon here 
int main() 
{ 
    int a=10, b=12; 
    SWAP(a, b); 
    printf("a = %d, b = %d\n", a, b); 
    return 0; 
} 
+2

где вы понимаете, что две точки с запятой должны вызывать ошибку? – filipe

+0

Почему «два полуколония должны произвести ошибку []]? Пробовали ли вы простой тест, чтобы убедиться, что компилятор принимает ';;' (без использования вашего макроса)? Производит ли он какие-либо ошибки или предупреждения? –

+1

«Два полуколония должны производить ошибку !!!» - Зачем? –

ответ

7

Бездомная запятая становится пустым заявлением, которое совершенно законно в C.

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

Отдельно макрос будет лучше записать в виде:

#define SWAP(a, b) do { int t = a; a = b; b = t; } while (0) 

Это работает лучше, если вы пытаетесь сделать два различных свопов в одном блоке кода.

+0

Несколько дней назад я увидел подобный пост, в котором ';;' вызвала большую проблему. Но я не помню, что это сообщение. – haccks

+0

Intriguing - вы можете это выкопать? –

+0

Да. В то время я запускаю этот код. Я ищу этот пост. – haccks

2

Полу-двоеточие само по себе представляет собой «пустое заявление», заявление, которое ничего не делает.

Иногда полезно, но большую часть времени это ошибка. Например, это Условный оператор не имеет желаемого эффекта:

if (x == y); 
{ 
    z=1; 
} 

Несмотря на этот факт, это вполне допустимо часть языка C.

2

После использования

gcc -E file_name.c вы получите для второго кода: -

int t; t=a, a=b, b=t;;

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

и эквивалентные

int t; t=a, a=b, b=t; 

; // null statement does nothing 
4

Дополнительные в точку с запятой местный охват никогда не приведет к ошибка в C (после C99), если используется как в вашем макросе. Они просто вводят пустой оператор. Откуда у вас возникла мысль, что это ошибка? Можно привести пример, который вызвал бы, скажем, ошибку «осиротевшего другого» из-за дополнительной точки с запятой, но ваш макрос не может использоваться под if в любом случае (см. Ниже).

В C89/90 можно было вызвать ошибку через непреднамеренно помещенную дополнительную точку с запятой после объявления, поскольку в C89/90 было запрещено смешивать объявления и утверждения. Например,

int a, b;; /* <- A declaration followed by an empty statement */ 
int c;  /* <- ERROR: Illegal declaration after a statement */ 

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

Стоит отметить, что такая реализация SWAP довольно бедна и довольно опасна.Это может привести к неожиданному, опасному и совершенно бессмысленному поведению в контекстах, как

if (/* whatever */) 
    SWAP(a, b); 

Лучше следовать do/while(0) идиомам и сделать что-то вроде

#define SWAP(a, b) do { int t; t=a, a=b, b=t; } while (0) 

Примечания - не точки с запятой в конце.

+0

Вы можете, конечно, сжечься на макросе if (X) macroA else, если 'macroA' генерирует бесплатный конец'; 'в конце. –

+0

@Hot Licks: Да, но макрос OP реализован как объявление, за которым следует инструкция. Такая реализация не используется undef' if' (как в вашем примере) для причинам, которые не имеют ничего общего с wi го хвоста ';'. Это не сработает (приведет к «осиротевшим другим») в этом контексте, независимо от того, существует ли в макросе конечный символ ';'. – AnT

+0

Оригинальный макрос, используемый с 'if' без фигурных скобок, пытается объявить' t' как тело 'if', но это недопустимо. Вещи идут вниз. –

Смежные вопросы