Абсурдная компиляция - PullRequest
       1

Абсурдная компиляция

3 голосов
/ 15 августа 2011

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

#include <stdio.h>

#include <stdlib.h>

int main(int argc, char *argv[])
{
    int a=f1();
    printf("a %d\n",a);
    system("PAUSE");    
    return 0;
}


f1(int *t)
{
       printf("t %d", t);
}

PS: я использую компилятор gcc на windows.

Ответы [ 6 ]

4 голосов
/ 15 августа 2011

В C, когда функция не объявлена, предполагается, что она возвращает int, и компиляция продолжается (кстати , это может привести к неприятным ошибкам ). Если функция объявлена ​​без типа (так как f1() в вашем коде, предполагается, что она вернет int. Не возвращать значение из функции, не являющейся пустым (как в вашем коде), - неопределенное поведение.

Так что ни один из упомянутых вами пунктов не должен вызывать ошибку компиляции. Неопределенное поведение не требуется для предотвращения запуска вашей программы - программа может запускаться и даже может давать хорошие результаты.

2 голосов
/ 15 августа 2011

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

C:\test>make
gcc -Wall prog.c -o prog
prog.c: In function 'main':
prog.c:7:5: warning: implicit declaration of function 'f1'
prog.c: At top level:
prog.c:14:1: warning: return type defaults to 'int'
prog.c: In function 'f1':
prog.c:16:8: warning: format '%d' expects type 'int', but argument 2 has type 'int *'
prog.c:17:1: warning: control reaches end of non-void function

Вы также можете использовать -Werror, чтобы превратить все предупреждения в ошибки (поэтому вы вынуждены их исправлять).

2 голосов
/ 15 августа 2011

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

x.c: In function 'main':
x.c:7: warning: implicit declaration of function 'f1'
x.c: At top level:
x.c:15: warning: return type defaults to 'int'
x.c: In function 'f1':
x.c:16: warning: format '%d' expects type 'int', but argument 2 has type 'int *'
x.c:17: warning: control reaches end of non-void function

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

1 голос
/ 15 августа 2011

f1 считается имеющим неявный прототип 'int f1 (int)'. Следовательно, вызов действителен. f1 ничего не возвращает, тогда как неявно предполагается возвращать int: поведение не определено. Компилятор может предупредить вас, что неявный прототип не соответствует определению. Это могло также попросить правильное возвращение. Это часть проверок, которые может выполнять статический анализ внутри компилятора: gcc этого не делает, другие могут. В любом случае компиляторы обычно не гарантируют ничего о программах, не соответствующих ISO.

1 голос
/ 15 августа 2011

Попробуйте снова скомпилировать с флагом -Wall. Это включает все предупреждения, тогда вы увидите много:

c.c: In function ‘main’:
c.c:7: warning: implicit declaration of function ‘f1’
c.c: At top level:
c.c:15: warning: return type defaults to ‘int’
c.c: In function ‘f1’:
c.c:16: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘int *’
c.c:17: warning: control reaches end of non-void function

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

0 голосов
/ 15 августа 2011

Если вы добавите -Wall к своим командам gcc, вы должны получить некоторые предупреждения.Я предполагаю, что это работает, поскольку старый стиль C имел слабое прототипирование функций.И примет неизвестные функции, возвращающие int.Компоновщик работал, потому что не было неопределенных символов (f1 существует), но вы получили мусор, поскольку то, что было передано в стек (т.е. ничего), не было тем, что ожидалось.

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