1
#include<stdio.h> 
int main() 
{ 
    //void foo(); 
    int c= 5; 
    c=foo(); 
    printf("\n%d",c); 
    return 0; 
} 
void foo() 
{ 
    printf("I am foo"); 
} 

Когда я комментирую заявление прототипа, то это дает результат:Что происходит, когда мы назначаем возвращаемое значение вызова функции с возвратом типа void в переменную int?

Я являюсь Foo

С прототипом он дает ошибку говоря:

Значение пустоты не игнорируется, как и должно быть.

Мой вопрос: что происходит внутри, что приводит к выводу, когда нет декларации прототипа? В чем причина этого?

Я использую редактор Dev C++ с TDM-GCC 4.9.2 64-битным компилятором.

+0

это будет UB. –

+1

Пациент: Доктор, мне больно, когда я это делаю. Доктор: Прекрати это делать! Что происходит, когда вы нарушаете контракт, который у вас есть с вашей реализацией, заключается в том, что ваша реализация может делать то, что чертовски хорошо хочет :-) – paxdiablo

ответ

3

Единственная причина, по которой это успешно построено, - это неявное правило int (теперь оно удалено в последней редакции стандарта C).

Компилятор не видит прямого объявления foo, поэтому предполагает, что его тип возврата - int. Затем он начинает строить и вызывает ваш void foo(). После того, как все сказано и сделано, поведение вашей программы не определено.

1

Компилятор Gcc дает предупреждение и успешно запускается, а возвращает количество символов с пробелами, но некоторые компиляторы дают сообщение об ошибке.

pp.c:10:6: warning: conflicting types for ‘foo’ [enabled by default] 
void foo() 
    ^
pp.c:6:6: note: previous implicit declaration of ‘foo’ was here 
    c=foo(); 
1

когда нет прототипа декларации

Ну, недействительна С.

Разрабатывать,

  • Пункт 1: Вы не может ve функция, которая не объявлена ​​ранее. Это противоречит стандарту C. Примечание

  • Пункт 2: Как только вы добавляете опережающее объявление, вы будете получать сообщение об ошибке компиляции, как void типа не может быть RHS операнда оператора присваивания и это является нарушением ограничений для оператор присваивания.


Примечание:

Pre C99, было разрешено иметь функцию вызывается без прототипа известно, предполагалось, что функция будет возвращать в int и будет принимать любое количество параметров. Однако это точно запрещено как на C99, так и позже, поскольку «неявное правило int» удаляется из стандарта.(см. П. 5, «удалить неявный int» в стандарте C99).

В вашем случае по устаревшим причинам компилятор по-прежнему поддерживает неявное правило int, поэтому он компилируется отлично, однако предположение со стороны компилятора и фактическое определение функции является несоответствием. Это вызывает undefined behavior.

Цитирование C11, глава §6.5.2.2, Вызовы функций

Если функция определена с типом, который не совместим с типом (выражения ) указывает, что выражение обозначает вызванную функцию, поведение - undefined.

+0

Это был C11, который удалил неявное правило int, нет? Однако я не уверен. Может быть C99. – StoryTeller

+0

@StoryTeller Nopes, я уверен, что это был C99. :) –

+0

Ну, у меня нет C99 для проверки. Не имеет значения, так как это была плохая идея, даже когда это было разрешено. – StoryTeller