По-моему, определять можно где угодно, лишь бы линкер увидел этот символ при сборке. Смысл объявления функции в теле другой функции, имхо, только в ограничении области видимости.
З.Ы. Товарищи, вы меня пугаете. Где вы тут С увидели? о_О
Не могли бы вы уточнить, что вы подразумеваете под термином «определять» и каких целей пытаетесь достичь?
Если я правильно понял, вы хотите создать функцию, предназначеную исключительно для внутреннего использования. В таком случае, вам стоит описать ее как локальную для данной единицы компилляции, используя ключевое слово static или безымянное пространство имен (С++).
// скрытие функции используя ключевое слово static
// эта функция видна только из того c/cpp файла, в котором она описана
static int g1()
{
return 1;
}
// скрытие функции используя безымянное пространство имен
// эта функция видна только из того cpp файла, в котором она описана
namespace
{
int g2()
{
return 2;
}
}
// эта функция находится в глобальном пространстве имен,
// и может быть использована из любого места в коде
void f()
{
std::cout << g1() << std::endl;
std::cout << g2() << std::endl;
}
Под термином «определять» подразумевается определение функции (имплементировать, реализовать), в отличие от «объявлять» - давать компилятору минимальную информацию о типе возвращаемого значения и типах и числе параметров. Суть вопроса: где должна быть имплементация, если объявление находится в теле другой функции? Ответ: где угодно, где это позволено синтаксисом языка (в теле другой функции, например, не позволено), главное чтобы при линковке тело функции оказалось в одном из линкуемых файлов. При объявлении функции в теле другой функции ее область видимости будет ограничена этим самым телом (от объявления и до символа «}» в конце функции). В приведенном вами примере видимость ограничена единицей компиляции, что, конечно же, совсем другое дело :)
Прошу прощения за многабукаф, в конце рабочего дня мысли компактно уже не выражаются...
roof:~/work/prog/cpp/sb$ cat fg.cpp
#include <iostream>
void f()
{
int g();
std::cout<<g()<<std::endl;
}
int h()
{
return g();
}
roof:~/work/prog/cpp/sb$ g++ -c fg.cpp -o fg.o
fg.cpp: In function ‘int h()’:
fg.cpp:11: ошибка: нет декларации ‘g’ в этой области видимости
>> По-твоему, оно не соберётся, потому что printf нигде не объявлен, чтоли?
а если вместо printf будет what_the_fuck_is_this_function(«Hello, world!\n»)?
И что? Чем what_the_fuck_is_this_function хуже printf? Ещё раз говорю — учи С. Ты либо не в курсе, что отсутствие объявления в С не является ошибкой, либо путаешь объявление с определением.
>Спасибо, кэп! Я, какбэ, иллюстрировал неправоту утверждающих, что в C отсутствим объявления является ошибкой.
Не отсутствием объявления. А вызовом функции, которая не была до этого определена в данном модуле или объявлена. Но суть от этого принципиально не меняется, не стоит придираться. Или у вас другие сакральные знания?
У топикстартера про С не было ни слова. Это раз. Вызов функции, которая не объявлена в текущей области видимости, в С++ является ошибкой. Это два. И незачем так орать (С) :)
>Ещё один, который считает, что отсутствие объявления функции до её вызова является ошибкой? В школу, учить С, строем по одному ШАГОМ А-А-А-АРШ!
Да считаю. В школе к сожалению такого не объясняют. Если вы считаете иначе, то будьте добры аргументируйте. Иначе демагогия.
В C89, искать «implicit function declaration». Из C99 упоминание убрали, но именно что убрали, а не обязали считать ошибкой. Я не знаю ни одного компилятора, который считал бы использование необъявленной функции ошибкой в умолчальной конфигурации.
И что с того что Вы не знаете такого компилятора? Язык не компилятор. С99 это стандарт и если не объявить функцию, то значит не придерживаться его. И не просто убрали упоминание, а именно убрали неявные объявления, писать так нельзя. В общем-то всё.
> И что с того что Вы не знаете такого компилятора? Язык не компилятор. С99 это стандарт и если не объявить функцию, то значит не придерживаться его.
Расскажи это разработчикам gcc, они будут рады. Ишь ты, стандарт нарушают, ироды, даже с '-std=c99 -pedantic' ошибкой не считают.
И не просто убрали упоминание, а именно убрали неявные объявления, писать так нельзя.
Убрали упоминание. Слов 'should not' я там не вижу. Это во-первых. Во-вторых и главных, «язык C» != «ISO/IEC 9899:1999». Фразы «согласно C99 вызов функции до её объявления может считаться ошибкой» и «отсутствие объявления функции в С является ошибкой» — две сильно разные фразы.
>Фразы «согласно C99 вызов функции до её объявления может считаться ошибкой» и «отсутствие объявления функции в С является ошибкой» — две сильно разные фразы.
Для меня это означает запрет, в своем коде неявных объявлений я делать не буду. Как делать Вам, дело Ваше, но писать, что так можно делать это излишне самонадеянно и по-моему как минимум не корректно. Повторю компилятор это не язык, стандарт нам говорит не использовать больше неявных объявлений, и компилятор об этом предупреждает.
Я не говорю, что так надо делать, я говорю, что неявное объявление в С есть и оно не является ошибкой. Так тяжело читать, что написано, а не между строк вычитывать, чего там не было?
Чтобы понятнее было, пример: использование в printf(3) аргумента не того типа, что описан в строке формата, не является ошибкой в С. Но является фигнёй, допускать которую нельзя.
Повторю компилятор это не язык
Yep. Один стандарт — тоже не язык.
стандарт нам говорит не использовать больше неявных объявлений
Хде стандарт такое говорит? Если бы в природе не существовало C89 и K&R, то тогда ой, но они, увы, были.
PS: Я вообще большой поклонник явного и нелюбитель умолчаний, а так же считаю, что весь код должен собираться без предупреждений при указании '-Wall', чтобы два раза не вставать уж. А то любите приписывать какую-то фигню, которую я не говорил...