(Я сначала начал писать программы на C где-то примерно в 1993 году. Тогда были другие времена, компиляторы могли быть другими, но я помню, что когда кто-то пытается сослаться на не объявленную функцию C, возникает ошибка. Кроме того, если функция будет определена позже, возможно, в другом единицы перевода, и "подписи" не совпадают, вы получите еще одну ошибку.)
В настоящее время я использую GCC 4.4.3. Я недоумеваю, почему GCC так снисходителен ко мне (в примере намеренно) несоответствующее (необязательное) объявление bar
и его определение в bar.c
, которое, очевидно, будет res ult в фатальной ошибке адресации - поскольку bar
хочет адрес и получает целое число, он заканчивает разыменованием этого целого числа как адреса. Строгий компилятор, по крайней мере, я так думаю, остановил бы меня с ошибкой. Я что-то пропустил? Моя командная строка сборки выглядит следующим образом:
cc -o foobar -g -Wall -std=c99 -fexec-charset=ISO-8859-1 -DDEBUG foo.c bar.c
С foo.c
:
int main()
{
int a;
bar(a);
return 0;
}
и bar.c
:
void bar(int * a)
{
*a = 1;
}
Я намеренно пропустил объявление bar
, а также намеренно передал ему целое число (на самом деле может быть что угодно) вместо адрес, как того требует его фактическое определение. Суть для меня: поскольку $ (CC) меня не останавливает, я получаю ошибку сегментации (x86, Ubuntu 10.04). Я знаю, что совместимый компилятор C (C99?) Неявно создает объявление int bar (void)
для bar
, если ничего не найдено, но в данном случае это явно не то, что я хочу вообще! Я хочу защитить себя от таких ошибок, когда я совершаю человеческую ошибку, несовпадая с декларациями и определениями или полностью опуская первые.
Вместо этого я попытался выполнить компиляцию только с помощью переключателя компилятора -c
, но это не имеет значения, так как он по-прежнему успешно с предупреждениями. Хотя компоновщик может заблокировать, но я хочу, чтобы компилятор остановил меня до того, как это произойдет.
Я не на самом деле хочу превращать свои предупреждения в ошибки с помощью, скажем, -Werror
, потому что:
полосу с плавающей запятой (двойная );
в верхней части foo.c
, что полностью устраняет предупреждение, но не меняет того факта, что результирующая программа выйдет из строя. Увы, программа, которая успешно компилируется без предупреждений (даже с переключателем -Wall
) и красиво вылетает во время выполнения.