Если не включить stdlib.h, ошибки компилятора не выдаются! - PullRequest
4 голосов
/ 26 января 2011

Надеюсь, это очень простой вопрос.Ниже приводится Cgg (test.c), который у меня есть.

#include <stdio.h>
//#include <stdlib.h>

int main (int argc, char *argv[]) {
    int intValue = atoi("1");
    double doubleValue = atof("2");
    fprintf(stdout,"The intValue is %d and the doubleValue is %g\n", intValue, doubleValue);
    return 0;
}

Обратите внимание, что я использую atoi () и atof () из stdlib.h, но я не включаю этот заголовочный файл.Я компилирую pgm (gcc test.c) и не получаю ошибки компилятора!

Я запускаю pgm (./a.out), и здесь вывод, который является неправильным.

The intValue is 1 and the doubleValue is 0

Теперь я включаю stdlib.h (удаляя комментарии перед #include), перекомпилирую и снова запускаю.На этот раз я получаю правильный вывод:

The intValue is 1 and the doubleValue is 2

Как получилось, что компилятор не жаловался на то, что не включил stdlib.h, и все же позволил мне использовать функции atoi (), atof ()?1013 * Информация о моем gcc:

$ gcc --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)

Любые мысли приветствуются!

Ответы [ 5 ]

12 голосов
/ 26 января 2011

По историческим причинам - в частности, совместимость с очень старыми программами на C (до C89) - использование функции без ее предварительного объявления только вызывает предупреждение от GCC, а не ошибку. Но предполагается, что тип возвращаемой функции такой: int, а не double, поэтому программа выполняется некорректно.

Если вы используете -Wall в командной строке, вы получите диагностику:

$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:5: warning: implicit declaration of function ‘atoi’
test.c:6: warning: implicit declaration of function ‘atof’

Вы должны использовать -Wall в основном всегда. Другими очень полезными опциями предупреждения для нового кода являются -Wextra, -Wstrict-prototypes, -Wmissing-prototypes, -pedantic и -Wwrite-strings, но по сравнению с -Wall они имеют гораздо более высокий уровень ложных срабатываний.

Тангенциально: никогда не используйте atoi или atof, они скрывают ошибки ввода. Вместо этого используйте strtol и strtod.

2 голосов
/ 26 января 2011

C позволяет вам вызывать функцию без объявления этой функции.

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

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

2 голосов
/ 26 января 2011

Если вы не укажете иное, я думаю, что компилятор C просто догадывается, что необъявленные функции принимают форму extern int foo()Вот почему atoi работает, а atof - нет.Какие флаги компилятора вы использовали?Я предлагаю использовать -Wall для включения нескольких предупреждений gcc, которые должны включать ссылки на необъявленные функции.

1 голос
/ 26 января 2011

В C, когда вы используете функцию, которая не была объявлена, предполагается, что она имеет прототип по умолчанию:

int FUNCTION_NAME();

Обратите внимание, что в C использование () в качестве прототипа означает, что она принимает любые аргументы.

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

0 голосов
/ 26 января 2011

C, к сожалению, не требует, чтобы функции были прототипированы (или даже объявлены) перед использованием - но без прототипа он автоматически делает определенные предположения о функции.Одним из них является то, что он возвращает int.В вашем случае atoi возвращает int, поэтому он работает правильно.atof нет, поэтому он не работает правильно.Не имея прототипа / объявления, вы получаете неопределенное поведение - как правило, в конечном итоге он извлекает любое значение в регистре, где обычно возвращается int, и использует его.Похоже, что в вашем конкретном случае это ноль, но это может быть и просто что-то еще.

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

...