Неожиданный успех кода C

0

Я тестирую следующий код в Code :: Blocks v 12.11:

#include <stdio.h>

int main()
{
    display();
    return 0;
}

void display()
{
    printf("\nHi");
}

Он успешно компилируется и работает хорошо. Я не могу понять, почему? Мои запросы следующие:

  1. Функция или переменная должна быть объявлена, по крайней мере, до использования в C/C++. Здесь нет объявления, прежде чем мы вызываем функцию display().

  2. По умолчанию все функции имеют тип возвращаемого значения как int.So, я ожидаю ошибку компиляции здесь, но он прошел успешно. Компилятор предположил бы, что display() будет int display(), а затем мы определили его как void display(),

  • 0
    вы правы, функция должна быть объявлена ранее в c, иначе это произойдет из-за ошибки.
  • 1
    Ваш второй пункт неверен. Вы определили тип возврата void, и ваша функция возвращает void. Я не думаю, что есть тип возврата по умолчанию для функций - вы должны определить тип возврата как часть определения функции.
Показать ещё 2 комментария
Теги:

2 ответа

-1
Лучший ответ

Ваш код отлично работает как.c файл и показывает ошибку, когда он выполняется как.cpp файл. Надеюсь, что этот пост объясняет, почему.

Почему декларация функции обязательна в C++, а не в C?

4

В C++ функции должны быть объявлены или определены перед использованием; этот код не может быть C++.

В C89 или pre-standard C, если компилятор встречает идентификатор, за которым следует открытая скобка, это вызов функции, и если в нем нет объявления или определения, тогда тип возврата неявно является int а число и типы аргументы не определены. (Таким образом, в примере display() - это функция, возвращающая int и принимающая неопределенное, но не переменное число аргументов.)

В C99 или C11, в любом режиме строгого соответствия, перед вызовом вы должны иметь объявление или определение функции в области. Он все еще не должен быть прототипом (inferred declaration int display(); не является прототипом, и определение также не является прототипом - для int display(void) прототипа нужно будет int display(void)).

Из-за выводимого типа для display() и противоречивого определения, я думаю, вы должны получить ошибку компиляции. Это было бы в лучшем случае неаккуратным компилятором, который разрешил бы это, даже в режиме C89. Действительно, я думаю, что даже предстандартный компилятор должен жаловаться на разницу между предполагаемыми и фактическими типами возврата, но, конечно, не было стандартного, поэтому вы не могли жаловаться (и, в любом случае, этому стандарту исполнилось 24 года - компиляторы, которые поддерживают только граничащие с архаикой).

Какой компилятор (и версия) вы используете на какой платформе?

GCC 4.8.2 на Mac OS X 10.9, даже если это возможно как можно более разрешительно, говорит:

dec.c:9:6: warning: conflicting types for ‘display [enabled by default]
 void display()
      ^
dec.c:5:5: note: previous implicit declaration of ‘display was here
     display();
     ^
  • 0
    В любом случае большинство версий GCC будут генерировать код - обратите внимание, что это всего лишь предупреждение, которое соответствует старому стандарту, согласно которому компилятор «должен диагностировать». Чтобы превратить это в ошибку, используйте -pedantic-errors или, в идеале, -pedantic-errors компилировать все с помощью -Werror (чтобы все ошибки -pedantic-errors как предупреждения) и содержите ваш код в чистоте (er).
  • 0
    Правда, это только предупреждение. Я забыл, что люди могут пытаться запускать код, несмотря на предупреждения во время компиляции - я этого не делаю, и я использую довольно строгие параметры, чтобы убедиться, что нет предупреждений о гораздо более неясных проблемах, чем этот.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню