Почему эта программа не выдает никаких предупреждений? - PullRequest
1 голос
/ 19 сентября 2011
#include<stdio.h>
void jigar (int ji)
{
    printf("%d",ji);
}
void main()
{
int a=32;
(jigar)(a);
}

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

(jigar)(a);

в этой строке. Теперь мой вопрос: почему gcc для linux не указывает на мою глупую ошибку?

Ответы [ 3 ]

3 голосов
/ 19 сентября 2011

почему (jigar) (a); не выдает предупреждение или ошибку?

Это вполне приемлемая конструкция для стандартного компилятора, совместимого со стандартом C (на что я не претендую gcc).
Это просто пара лишних лишних скобок вокруг имени функции, разрешающая то же самое, что и имя функции, сама по себе ... или окруженная еще большим количеством скобок.

/* assuming `jigar` is a honest-to-God function
** all 3 statements below "do" the same thing */
jigar(a);
(jigar)(a);
(((((((jigar)))))))(a);

Я видел, как он использовался в реальной жизни для предотвращения расширения макроса (хотя пример был составлен прямо сейчас).

#include <stdio.h>

#define MACRO(x) ((x) - 42)

int (MACRO)(int x) { return 42 + x; } /* does not expand MACRO! */

int main(void) {
    printf(" MACRO  ==> %d\n", MACRO(100));   /* expand */
    printf("(MACRO) ==> %d\n", (MACRO)(100)); /* do not expand */
    return 0;
}

Вы можете видеть приведенный выше код, работающий на кодовой панели и на ideone .

И main возвращает int, а не void.

3 голосов
/ 19 сентября 2011

Нет ничего плохого в (jigar)(a);, поскольку это допустимо в стандарте C. Причина, по которой ваш компилятор MIPS выдает предупреждение, заключается в том, что, возможно, этот компилятор не полностью реализует стандарт C.

Редактировать: Относительно запроса Алса, почему это стандартный C, вот как:

Посмотрите на грамматику ISO C здесь: http://www.cs.dartmouth.edu/~mckeeman/cs48/mxcom/doc/notation/c.html и обратите внимание, что вызов функции

postfix-expression -> postfix-expression ( )
                    | postfix-expression ( argument-expression-list )

может иметь postfix-expression в качестве функции. Существует правило, которое гласит:

postfix-expression -> primary-expression

где primary-expression может быть identifier, то есть именем функции. Однако есть и это правило:

primary-expression -> ( expression )

и если вы будете следовать цепочке правил с expression, вы снова вернетесь к primary-expression. Следовательно, косвенно, у вас есть:

primary-expression -> ... -> ( primary-expression ) -> ( identifier )

Семантика C указывает, что ( expression ) имеет тот же тип и значение, что и expression (1). Согласно грамматике, (jigar) (а) является правильным. Семантически (jigar) и jigar имеют одинаковый тип и значение. Поэтому C принимает (jigar)(a), а функциональность такая же, как jigar(a).

Редактировать 2:

(1) Проект раздела C99 6.5.1, статья 5:

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

P.S. Кто-нибудь знает, где я могу получить документацию для ISO C, как список функций или что-то? Я видел, как люди цитировали это, но я не мог найти это сам.

1 голос
/ 19 сентября 2011

Единственная ошибка, которую я вижу в вашем коде, заключается в том, что ваш main возвращает void, тогда как должен возвращать int.

gcc 4.4.3 с -Wallподнимает это.

Если вы ссылаетесь на круглые скобки вокруг (jigar), это допустимо C. Если вашему компилятору MIPS это не нравится, то это проблема с компилятором MIPS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...