LINUX.ORG.RU

Вопрос по C


0

0

Можно ли в C объявлять функции внутри других функций?

Можно ли сделать неглобальную переменную доступной для нескольких функций?

Что мне нужно. Из одной функции многократно вызывается другая. Она вычисляет функцию от полутора десятков параметров. Два меняются с каждым вызовом, остальные -- только с новым прогоном программы. Для примера: return a*x+b*y+c*x*y+d*x*x/y... Что можно сделать, чтобы не передавать a, b, c и d при каждом вызове функции? Глобальные переменные пробовал, но всё время возникают конфликты имён с библиотеками.

Извините за сумбурность, терминологией владею плохо. Ключевые слова для поиска ответа в гугле приветствуются. Ссылки на примеры -- тоже.

★★★

>>Можно ли в C объявлять функции внутри других функций?

нет

>>Можно ли сделать неглобальную переменную доступной для нескольких функций?

можно использовать модификатор static и вынести необходимые функции в отдельный файл (переменная будет находиться в видимости одного файла)

кстати, передача полутора десятков параметров это совсем нехорошо

help_us
()

> Можно ли в C объявлять функции внутри других функций?

В стандарте C -- нельзя. В GNUтых расширениях -- можно. С обычным предупреждением относительно портабельности.

http://en.wikipedia.org/wiki/Nested_function

> Можно ли сделать неглобальную переменную доступной для нескольких функций?

Нет, нельзя.

> Что можно сделать, чтобы не передавать a, b, c и d при каждом вызове функции?

Первое, что приходит на ум -- это static. Но я сильно невыспавшийся...

Uncle_Theodore ★★
()

А нельзя ли зафигачить содержимое той ф-ии, которая вызывается, в ту которая вызывает?

anonymous
()
Ответ на: комментарий от help_us

>>>Можно ли сделать неглобальную переменную доступной для нескольких функций?

>можно использовать модификатор static и вынести необходимые функции в отдельный файл (переменная будет находиться в видимости одного файла)

Спасибо. Можно ссылку на пример?

> кстати, передача полутора десятков параметров это совсем нехорошо

Согласен. Поэтому и спрашиваю.

olegd ★★★
() автор топика
Ответ на: комментарий от Uncle_Theodore

> В стандарте C -- нельзя. В GNUтых расширениях -- можно. С обычным предупреждением относительно портабельности.

> http://en.wikipedia.org/wiki/Nested_function

Оно, спасибо. В GCC 3.x это должно работать?

olegd ★★★
() автор топика
Ответ на: комментарий от anonymous

> А нельзя ли зафигачить содержимое той ф-ии, которая вызывается, в ту которая вызывает?

Она вызывается из нескольких мест. Кроме того, от этого программа хуже читается. Конечно, можно.

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

> В GCC 3.x это должно работать?

Потому, что на пример из википедии ругается

In function `float E(float)':

error: syntax error before `{' token

olegd ★★★
() автор топика

Ещё можно компилировать с ключом -O2 и понадеяться на gcc.

naryl ★★★★★
()

>Можно ли в C объявлять функции внутри других функций? зачем вам это?

>Что мне нужно. Из одной функции многократно вызывается другая. Она вычисляет функцию от полутора десятков параметров. Два меняются с каждым вызовом, остальные -- только с новым прогоном программы. Для примера: return a*x+b*y+c*x*y+d*x*x/y... Что можно сделать, чтобы не передавать a, b, c и d при каждом вызове функции? Глобальные переменные пробовал, но всё время возникают конфликты имён с библиотеками. во-первых, в детских сказках говорится, что глобальные переменные - зло, во-вторых, если много параметров - передавайте их либо в структуре, если он не однородные, либо в массиве, если однородные

вы не хотите передавать параметры функции для более высокой производительности? пользуйтесь тогда модификатором inline. Но вы таки еще и обеспокоены объемом программы? тогда да, пользуйтесь модификатором static - переменная будет глобальной в файле, в котором объявлена. Тогда надо иметь функцию для инициализации подобных переменных перед началом работы.

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

Кстати, да, посмотрите, что там с областью видимости у вложенных функций в расширениях гсс. Если область видимости автоматических переменных "родительской" функции распространяется на вложенную функцию, тогда ваша проблема, судя по всему, решена.

>Извините за сумбурность, терминологией владею плохо. Ключевые слова для поиска ответа в гугле приветствуются. Ссылки на примеры -- тоже. Читайте Кернигана-Ритчи до просветления. Надеюсь, уже начли.

anonymous
()

>Можно ли в C объявлять функции внутри других функций?

зачем вам это?

>Что мне нужно. Из одной функции многократно вызывается другая. Она вычисляет функцию от полутора десятков параметров. Два меняются с каждым вызовом, остальные -- только с новым прогоном программы. Для примера: return a*x+b*y+c*x*y+d*x*x/y... Что можно сделать, чтобы не передавать a, b, c и d при каждом вызове функции? Глобальные переменные пробовал, но всё время возникают конфликты имён с библиотеками.

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

вы не хотите передавать параметры функции для более высокой производительности? пользуйтесь тогда модификатором inline. Но вы таки еще и обеспокоены объемом программы? тогда да, пользуйтесь модификатором static - переменная будет глобальной в файле, в котором объявлена. Тогда надо иметь функцию для инициализации подобных переменных перед началом работы.

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

Кстати, да, посмотрите, что там с областью видимости у вложенных функций в расширениях гсс. Если область видимости автоматических переменных "родительской" функции распространяется на вложенную функцию, тогда ваша проблема, судя по всему, решена.

>Извините за сумбурность, терминологией владею плохо. Ключевые слова для поиска ответа в гугле приветствуются. Ссылки на примеры -- тоже.

Читайте Кернигана-Ритчи до просветления. Надеюсь, уже начли.

anonymous
()

>Что можно сделать, чтобы не передавать a, b, c и d при каждом вызове функции?

Запихни их в глобальную структуру

ttnl ★★★★★
()
Ответ на: комментарий от olegd

Как уже посоветовал анонимный коллега - параметры в виде структуры и inline спасут отца русской демократии.

struct params_t
{
  ...
};

inline void sub_make( params_t * params )
{
  ...
}

void make( params_t * params )
{
  sub_make( params );
}

Dendy ★★★★★
()
Ответ на: комментарий от Dendy

> параметры в виде структуры и inline

Спасибо, думал, но не пробовал. Кстати, в C есть эквивалент паскалевскому with? То есть конструкция, которая позволяет опускать часть имени элемента структуры (внутри блока автоматически подставляет имя структуры там, где оно пропущено)?

olegd ★★★
() автор топика
Ответ на: комментарий от anonymous

> Если функция мелкая - можно заменить ее макросом.

Спасибо. Чем макрос принципиально отличается от inline? Помимо того, что подставляется на другом этапе.

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

Тем, что его придётся отлаживать в уме

anonymous
()
Ответ на: комментарий от anonymous

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

Нет, их много.

> Кстати, да, посмотрите, что там с областью видимости у вложенных функций в расширениях гсс. Если область видимости автоматических переменных "родительской" функции распространяется на вложенную функцию, тогда ваша проблема, судя по всему, решена.

С самого начала так и хотел. Когда не заработало (IDE автоматически все *.c файлы обрабатывает как CPP) -- начал искать в документации и ничего не нашёл. Решил, что, может, путаю C с чем-то ещё. Спросил.

> Читайте Кернигана-Ритчи до просветления. Надеюсь, уже начли.

Там нашёл только макросы. Даже inline нету.

olegd ★★★
() автор топика

А Вы не можете выделить неизменяемые параметры в структуру? 
Это намного лучше чем глобальные переменные.

typedef struct ConstParamsTag
{
    int param1;
    float param2;
    char param3;
} ConstParams;

void Inner(ConstParams* paramsConst, int arg1, double arg2)
{
.....
}

void Outer()
{
    ConstParams p;
    p.param1=42;
    p.param2=1.0;
    /*.......*/
    Inner(&p, 1, 3);
    Inner(&p, 4, 7);
}

gzh
()
Ответ на: комментарий от olegd

>Там нашёл только макросы. Даже inline нету.

Еще б они там были. K&R это ANSI C. А inline это ISO C99

Dudraug ★★★★★
()
Ответ на: комментарий от olegd

> Даже inline нету.

компилятор может инлайнить даже если слова inline нет. Слово inline нужно только для того чтобы функцию можно было поместить в хедер и вызывать в разных единицах компиляции и не иметь проблем с линкером.

К тому же если идет рекурсивный вызов, то от inline как бы не очень много толку.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> компилятор может инлайнить даже если слова inline нет

Через макросы или как-то ещё?

> К тому же если идет рекурсивный вызов, то от inline как бы не очень много толку.

А что будет если вызывать инлайновую функцию рекурсивно?

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

> Через макросы или как-то ещё?

если функции в одной единице трансляции -- компилятор видит определение функции -- кто ему мешает ее инлайнить? Собственно, gcc может инлайнить и не inline функции.

> А что будет если вызывать инлайновую функцию рекурсивно?

Ну в принципе компилятор может на некую конечную глубину ее таки развернуть -- примерно так же как при раскрутке цикла.

dilmah ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.