2013-08-22 4 views
1

У меня есть следующая программаОчень простая программа C не будет скомпилирована в GCC компилятора

main() 
{ 
    char a,b; 
    printf("will i get the job:"); 
    scanf("%c",&a); 
    printf("%c",a); 
    printf("We did it"); 
} 

я сохранил файл как Hope.c. Когда я пытаюсь скомпилировать код, приведенный выше с компилятором GCC, я получаю следующее сообщение об ошибке:

Hope.c:In function 'main': 
Hope.c:4:2:warning:incompatible implicit declaration of built-in function 'printf' [enabled by default]   
Hope.c:5:2:warning:incompatible implicit declaration of built-in function scanf[enabled by default] 

Компилятор дает эту ошибку, когда я использую printf() или scanf(), даже в простом «привет мир» программы.

С моим кодом что-то не так, или проблема с компилятором?

+6

Добавить '#include ' наверху. Также удалите тег 'C++'. – BoBTFish

+0

Вам нужно #include

+1

Один короткий отрезок почти во всех случаях, когда вы получаете предупреждение, например * warning: несовместимое неявное объявление встроенной функции '** любая функция **' [включено по умолчанию] *, искать правильные файлы заголовков – 0decimal0

ответ

4

Когда вы вызываете функции, с которыми вы не знакомы, посмотрите на страницу руководства, а включите заголовки, упомянутые там. Это #include <stdio.h> в вашем случае.

Это действительно очень важно, например. Я испытал printf("%s", func()), вызвав ошибку сегментации, хотя func() вернул действительную строку с нулевым завершением, но не было прототипа, который объявлял тип возврата func() как char * (делая небольшое исследование, мы обнаружили, что только последние четыре байта 64-битного указатель был отправлен в printf())

2

Да, с кодом что-то не так. Вы используете функции printf и scanf, не объявляя их.

Обычная вещь, чтобы сделать, это использовать заявления погруженные с компилятором (потому что они, как известно, правильно) с

#include <stdio.h> 
6

Вы упускаете #include <stdio.h> в верхней части. Обратите внимание, что это были предупреждения, но не ошибки. Ваша программа все равно должна быть скомпилирована как есть.

Кроме того, для хорошей меры вы должны написать тип возврата и параметры для main() и вернуть значение в конце.

#include <stdio.h> 

int main(void) 
{ 
    char a,b; 
    printf("will i get the job:"); 
    scanf("%c",&a); 
    printf("%c",a); 
    printf("We did it"); 

    return 0; 
} 
+0

, хотя вы абсолютно правы, я хочу добавить, что эти предупреждения могут привести к сбою во время выполнения, например. Я видел 'printf ("% s ", func())' throwing seg fault, хотя 'func()' возвращал допустимую строку только потому, что не было прототипа, который объявлял бы тип возвращаемого значения как 'char *' –

+1

стандарт 1999 года, 'return 0;' не нужен, потому что он неявчив в достижении закрывающего '}' - хотя ИМХО, это все еще неплохая идея. Также, как и в стандарте 1999 года, вызов любой функции без видимого объявления является нарушением ограничения, требующим диагностики времени компиляции. (Декларация все еще не обязана быть прототипом *, но все объявления функций указывают тип возврата.) –

+0

Это сработало! Спасибо! – user2469493

2

C.89/C.90 допускает неявные декларации функций. Ваши предупреждающие сообщения сообщают вам, что вы не указали явные декларации для scanf и printf. Как уже упоминалось, вы можете исправить это, добавив #include <stdio.h> в начало вашей программы. Не делая этого, поведение вашей программы не определено.

Поскольку scanf() и printf() имеют неявные декларации, они рассматриваются, как если бы были даны их прототипы, как:

extern int scanf(); 
extern int printf(); 

Эти заявления утверждают, что scanf() и printf() принять как еще неизвестное количество аргументов и возвращаемых и int , Однако этот вид декларации по-прежнему предполагает, что эти функции будут принимать фиксированное количество аргументов.Это несовместимо с их истинными прототипами, в которых они принимают переменное число аргументов:

extern int scanf (const char *, ...); 
extern int printf (const char *, ...); 

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

Компилятор, у которого не было этого «встроенного знания», вероятно, не вызвал бы предупреждения. Затем он сгенерировал код для вызова scanf() и printf(), как если бы они приняли фиксированное количество аргументов. Ошибка может возникнуть во время выполнения, поскольку соглашение о вызове для функции, которая принимает переменное количество аргументов, может отличаться от вызывающего соглашения функции, которая принимает фиксированное количество аргументов.

Все это описано в C.89 § 3.3.2.2.

If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration
extern int identifier();
appeared.
...
If the expression that denotes the called function has a type that does not include a prototype, the integral promotions are performed on each argument and arguments that have type float are promoted to double. ... If the function is defined with a type that includes a prototype, and the types of the arguments after promotion are not compatible with the types of the parameters, or if the prototype ends with an ellipsis (" , ... "), the behavior is undefined.

Обратите внимание, что C.99 удаляет учет неявных деклараций функций.

+0

Нам действительно нужны три абзаца, чтобы объяснить, что OP забыл добавить заголовок? – Jiminion

+3

@ Jim: Это объясняет три вещи: (1) что является неявным объявлением, (2) почему есть предупреждающее сообщение, если неявные объявления разрешены, и (3) почему использование неявного объявления функции который принимает переменное количество аргументов, приводит к неопределенному поведению. – jxh

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