Код по-прежнему выполняется без каких-либо включений (Dev-C ++ Bloodshed) - PullRequest
2 голосов
/ 01 августа 2009

В настоящее время я изучаю и экспериментирую с C и использую DEV-C ++ Bloodshed в качестве IDE.

Теперь я только что понял, что следующий фрагмент кода (как он есть ... не включает или ничего) компилируется и запускается:

main ()
{
    printf("%d", strlen("hello"));  
}

Теперь, если я не ошибаюсь, не должны ли два файла заголовков быть включены в этот источник для его работы? stdio.h и string.h ... но, как вы можете видеть, я не добавил их, а код все еще компилировался и успешно работал.

Моя жалоба на то, что я хочу, чтобы компилятор был "строгим", потому что, поскольку я все еще изучаю C, я не хочу, чтобы код выполнялся, если обычно это не должно.

Итак, есть ли способ помешать Dev-C ++ «исправить мои ошибки», когда дело доходит до include s, то есть сделать его более «строгим»?

Ответы [ 3 ]

7 голосов
/ 01 августа 2009

C90 имеет функцию (отсутствует в C99 и C ++), называемую неявным объявлением функции: когда вы использовали имя, еще не объявленное в вызове функции, компилятор вел себя так, как если бы

extern int identifier();

было замечено. Эта функция была удалена из C99, и большинство компиляторов имели возможность предупреждать об этом еще до того, как C99 был обнародован.

Даже если вы остаетесь в C90, не рекомендуется использовать этот стиль. Если вам нужно поддерживать код, использующий это, и не можете добавлять прототипы, проверьте, что:

  • функции возвращают int (это имеет место для printf, но валидность зависит от реализации для strlen, который возвращает size_t, который может быть int или чем-то еще)

  • функция не переменная (это относится к strlen, но не printf)

  • тип аргументов не изменяется по умолчанию при продвижении аргументов (char, short, float is), и вы должны обратить внимание на приведение указателей на void * при необходимости, когда ожидаемый тип void *, вы должны обратите внимание на приведение NULL к правильному типу указателя. (Это те же самые вещи, на которые вы должны обращать внимание при различных аргументах, кстати).

Если эти условия не выполнены - и они не предназначены для вызовов в вашем коде - вы входите в область неопределенного поведения.

4 голосов
/ 01 августа 2009

Я не знаю, действительно ли это проблема DevC ++, но в любом случае вам стоит подумать об этом. Он больше не разрабатывается и очень глючит. Я рекомендую изменить на Code :: Blocks , что лучше во всех отношениях и позволяет использовать самый последний компилятор GCC.

0 голосов
/ 01 августа 2009

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

Если вы используете gcc в качестве базового компилятора, вы сможете передавать флаги, такие как -std=c89 -pedantic -Wall -Wextra, и получать предупреждения о коде, таком как фрагмент, который вы опубликовали.

...