Как вызвать void функцию c
В языке программирования C функция тоже имеет адрес и может иметь указатель. Указатель на функцию представляет собой выражение или переменную, которые используются для представления адреса функции. Указатель на функцию содержит адрес первого байта в памяти, по которому располагается выполняемый код функции.
Самым распространенным указателем на функцию является ее имя. С помощью имени функции мы можем вызывать ее и получать результат ее работы.
Но также указатель на функцию можно определять в виде отдельной переменной с помощью следующего синтаксиса:
тип (*имя_указателя) (типы_параметров);
Здесь тип представляет тип возвращаемого функцией значения.
имя_указателя представляет произвольно выбранный идентификатор в соответствии с правилами о наименовании переменных.
После названия указателя в скобках идут через запятую типы параметров. Если функция не принимает параметров, то указывается void .
Например, определим указатель на функцию:
void (*message) (void);
Здесь определен указатель, который имеет имя message . Он может указывать на функции без параметров, которые возвращают тип void (то есть ничего не возвращают). После названия указателя идет (void) , что указывает, что функция не принимает параметров.
Применим этот указатель на функцию:
#include void hello() < printf("Hello, World \n"); >void goodbye() < printf("Good Bye, World \n"); >int main(void) < // определяем указатель на функцию void (*message) (void); message=hello; // указатель указывает на функцию hello message(); // вызываем функцию, на которую указыывет указатель message = goodbye; // указатель указывает на функцию goodbye message(); // вызываем функцию, на которую указыывет указатель return 0; >
Указателю на функцию можно присвоить функцию, которая соответствует указателю по возвращаемому типу и спецификации параметров:
message=hello;
То есть в данном случае указатель message теперь хранит адрес функции hello. И посредством обращения к указателю мы можем вызвать эту функцию:
message();
Впоследствии мы можем присвоит указателю адрес другой функции, как в данном случае. В итоге результатом данной программы будет следующий вывод:
Hello, World Good Bye, World
При определении указателя стоит обратить внимание на скобки вокруг имени. Так, использованное выше определение
void (*message) (void);
НЕ будет аналогично следующему определению:
void *message (void);
Во втором случае определен не указатель на функцию, а прототип функции message, которая возвращает указатель типа void* .
Следует учитывать, что указатель на функцию должен по типу возвращаемого значения и типу параметров соответствовать функции, иначе он не сможет соответствовать этой функции.
Рассмотрим еще один указатель на функцию, которая возвращает значение типа int и принимает два параметра типа int :
#include int add(int x, int y) < return x + y; >int subtract(int x, int y) < return x - y; >int main(void) < int a = 10; int b = 5; int result; int (*operation)(int, int); operation=add; result = operation(a, b); printf("result = %d \n", result); // result=15 operation = subtract; result = operation(a, b); printf("result = %d \n", result); // result=5 return 0; >
Здесь определен указатель operation, который может указывать на функцию с двумя параметрами типа int , возвращающую также значение типа int . Соответственно мы можем присвоить указателю адреса функций add и subtract и вызвать их, передав при вызове в указатель нужные значения для параметров.
Массивы указателей на функции
Кроме одиночных указателей на функции мы можем определять их массивы. Для этого используется следующий формальный синтаксис:
тип (*имя_массива[размер]) (параметры)
double (*actions[]) (int, int)
Здесь actions представляет массив указателей на функции, каждая из которых обязательно должна принимать два параметра типа int и возвращать значение типа double .
Посмотрим применение массива указателей на функции на примере:
#include void add(int x, int y) < printf("x + y = %d \n", x + y); >void subtract(int x, int y) < printf("x + y = %d \n", x - y); >void multiply(int x, int y) < printf("x * y = %d \n", x * y); >int main(void) < int a = 10; int b = 5; void (*operations[3])(int, int) = ; // получаем длину массива int length = sizeof(operations)/sizeof(operations[0]); for(int i=0; i < length; i++) < operations[i](a, b); // вызов функции по указателю >return 0; >
Здесь массив operations содержит три функции add, subtract и multiply, которые последовательно вызываются в цикле через перебор массива в функции main.
Функции
Функция определяет действия, которые выполняет программа. Функции позволяют выделить набор инструкций и назначить ему имя. А затем многократно по присвоенному имени вызывать в различных частях программы. По сути функция — это именованный блок кода.
Формальное определение функции выглядит следующим образом:
тип имя_функции(параметры)
Первая строка представляет заголовок функции. Вначале указывается возвращаемый тип функции. Если функция не возвращает никакого значения, то используется тип void .
Затем идет имя функции, которое представляет произвольный идентификатор. К именованию функции применяются те же правила, что и к именованию переменных.
После имени функции в скобках идет перечисление параметров. Функция может не иметь параметров, в этом случае указываются пустые скобки.
После заголовка функции в фигурных скобках идет тело функции, которое содержит выполняемые инструкции.
Для возвращения результата функция применяет оператор return . Если функция имеет в качестве возвращаемого типа любой тип, кроме void, то она должна обязательно с помощью оператора return возвращать какое-либо значение.
Например, определение функции main, которая должна быть в любой программе на языке C++ и с которой начинается ее выполнение:
int main()
Возвращаемым типом функции является тип int , поэтому функция должна использовать оператор return и возвращать какое-либо значение, которое соответствует типу int. Возвращаемое значение ставится после оператора return.
Стоит отметить, что С++ позволяет не использовать оператор return в функции main:
int main()
Но если функция имеет тип void , то ей не надо ничего возвращать. Например, мы могли бы определить следующую функцию, которая просто выводит некоторый текст на консоль:
void hello()
Выполнение функции
Когда запускается программа на языке C++, то запускается функция main. Никакие другие функции, определенные в программе, автоматически не выполняются. Для выполнения функции ее необходимо вызвать. Вызов функции осуществляется в форме:
имя_функции(аргументы);
После имени функции указываются скобки, в которых перечисляются аргументы — значения для параметров функции.
Например, определим и выполним простейшую функцию:
#include void hello() < std::cout int main()
Здесь определена функция hello, которая вызывается в функции main два раза. В этом и заключается преимущество функций: мы можем вынести некоторые общие действия в отдельную функцию и затем вызывать многократно в различных местах программы. В итоге программа два раза выведет строку «hello».
hello hello
Объявление функции
При использовании функций стоит учитывать, что компилятор должен знать о функции до ее вызова. Поэтому вызов функции должен происходить после ее определения, как в случае выше. В некоторых языках это не имеет значение, но в языке C++ это играет большую роль. И если, к примеру, мы сначала вызовем, а потом определим функцию, то мы получим ошибку на этапе компиляции, как в следующем случае:
#include int main() < hello(); hello(); >void hello()
В этом случае перед вызовом функции надо ее дополнительно объявить. Объявление функции еще называют прототипом. Формальное объявление выглядит следующим образом:
тип имя_функции(параметры);
Фактически это заголовок функции. То есть для функции hello объявление будет выглядеть следующим образом:
void hello();
Используем объявление функции:
#include void hello(); int main() < hello(); hello(); >void hello()
В данном случае несмотря на то, что определение функции идет после ее вызова, но так как функция уже объявлена до ее вызова, то компилятор будет знать о функции hello, и никаких проблем в работе программы не возникнет.
Как вызвать функцию?
Как вызвать функцию ?
Вот у меня есть вот такая функция как её вызвать ? void CAimbot::pSilent(CUserCmd* pCmd)
Как вызвать функцию
Хочу создать хранилище , у базового класса есть функция virtual void parametri() < cout << ".
Как вызвать функцию ?
Не получается вызвать значение функции из number #include <iostream> int number(int x) < x.
270 / 176 / 46
Регистрация: 12.03.2010
Сообщений: 494
Если у них сигнатуры одинаковые то вполне логично юзать указатель на функцию
Первое что в голову пришло, хотя я бы от такого кода воздержался в реальных разработках
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#define FUNC(num) &print##num using namespace std; void print1() { cout "print1" endl; } void print2() { cout "print2" endl; } typedef void (*funcPtr)(void); int main() { funcPtr func = FUNC(1); (*func)(); system("pause"); return 0; }
Регистрация: 27.05.2010
Сообщений: 6
а мне нужно чтобы в 17 строке
funcPtr func = FUNC(1);
я вместо 1 мог указать какуюто переменную
скажем FUNC(ss);
а он сразу говорит что printss незадекларированная
2021 / 1620 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
Сообщение от marat1
У меня допустим есть уже готовые функции с именами от а0 до а1000
Честно говоря уже попахивает извращением. Для чего такое понадобилось, если не секрет?
Сообщение от marat1
а мне нужно чтобы прога исходя из входных данных сама высчитала число, добавила его к а, и потом запустила соответствующую функцию
Массив указателей на функции.
Регистрация: 27.05.2010
Сообщений: 6
rangerx просту у меня есть функция которая должна в свою очередь запускать иные уже готовые функции. каждый раз изходя из вводных параметров имя фукции меняется
пример
если переременная а = 10
то нужно запустить функцию b10()
может ето дело кто нибуть перевести ето дело в рабочий, минимальній код. Пожалуйста, я новичок.
Добавлено через 19 минут
rangerx просту у меня есть функция которая должна в свою очередь запускать иные уже готовые функции. каждый раз изходя из вводных параметров имя фукции меняется
пример
если переременная а = 10
то нужно запустить функцию b10()
может ето дело кто нибуть перевести ето дело в рабочий, минимальній код. Пожалуйста, я новичок.
Добавлено через 27 минут
Manjak а что ты можешь сказать?
2021 / 1620 / 489
Регистрация: 31.05.2009
Сообщений: 3,005
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include void a0(){ puts("in a0"); } void a1(){ puts("in a1"); } void a2(){ puts("in a2"); } typedef void (*pFunc)(); int main() { pFunc func[3] = {a0, a1, a2}; func[0](); func[1](); func[2](); return 0; }
Как вызвать функцию как аргумент?
Смысл такой, что нужно расписать программу для сортировки массива по функциям без использования глобальных переменных. Я решил пойти путём вызова функций как параметров для функций(ведь это же можно сделать с помощью указателей. ) Листинг моего «чудо»-кода:
#include #include using namespace std; void print(double a[10]) < //double a[10]; for (int i = 0; i < 10; i++) < cout > double find_min_element(double a[10]) < double var; // double a[10]; int n = 10; var = 9223372036854775807; int index = 0; for (int i = 0; i < n - 1; i++) < if (a[i] < var) < var = a[i]; index = i; >> return index; > double sort_array(double a[10]) < //double a[10]; int m; int n = 10; for (int i = 0; i < n; i++) < m = i; for (int j = i + 1; j < n; j++) < if (a[j] < a[i]) < m = j; swap(a[i], a[m]); >> cout return a[n]; > double filling() < int i; double a[10]; int n = 10; cout > a[i]; > return a[i]; > int main(int argc, char** argv) < //using pointer_to_function = double(*)(); //int (*pointerToFunction)(double ) = NULL; //pointerToFunction = &filling; pointer_to_function ptf = filling; filling(); find_min_element( ptf); /*В find_min_element надо отправить заполненный массив. Такой у нас имеется после вызова filling. Так как глобальные переменные использовать нельзя, то получается, что в main'е зацепить массив в переменную я не могу*/ print(ptf); return 0; >
На выходе компилятор выдаёт следующие ошибки
g++ -Wall -c «Functions.cxx» (в каталоге: /home/alex/Yandex.Disk/Программирование/1D_arrays_from_functions) Functions.cxx: In function ‘int main(int, char**)’: Functions.cxx:94:8: error: expected nested-name-specifier before ‘pointer_to_function’ using pointer_to_function = double(*)(); ^ Functions.cxx:97:2: error: ‘pointer_to_function’ was not declared in this scope pointer_to_function ptf = filling; ^ Functions.cxx:99:19: error: ‘ptf’ was not declared in this scope
find_min_element(ptf);
^ Сборка завершилась с ошибкой.
Среда — Geany, g++. ^ — разделитель между ошибками.
Отслеживать
218k 15 15 золотых знаков 117 117 серебряных знаков 229 229 бронзовых знаков
задан 18 фев 2017 в 5:13
39 7 7 бронзовых знаков
Из того, что «глобальные переменные использовать нельзя», следует, что надо использовать локальные переменные. К чему тут вдруг указатели не функции — не ясно.
18 фев 2017 в 9:36
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Вы уж извините, но у вас код. Давайте по нему пройдемся.
void print(double a[10]) < //double a[10]; for (int i = 0; i < 10; i++) < cout >
Пожалуй, одна из реально работающих функций 🙂
double find_min_element(double a[10]) < double var; int n = 10; var = 9223372036854775807;
Что за странная константа? Тем более что double такую точность не поддерживает, и все равно ее обрежет. А если вы хотели максимальное значение double , так это numeric_limits::max() .
int index = 0; for (int i = 0; i < n - 1; i++)
Почему вы не рассматриваете последний элемент массива? И вообще - зачем вводить переменную, если это у вас - жестко прошитая константа?
double sort_array(double a[10])
Честно говоря, на беглый взгляд вроде и ничего. но зачем эта переменная m ? int m;
И что вы возвращаете? Несуществующий элемент массива? Зачем? return a[n]; >
double filling() < int i; double a[10]; int n = 10; cout > a[i]; >
Допустим. Заполнили. Заполнили локальный массив, который при выходе из функции исчезнет.
return a[i];
И опять вернули несуществующий элемент.
int main(int argc, char** argv) < //using pointer_to_function = double(*)();
Это правильное объявление типа для указателя на filling , только раскомментировать 🙂
//int (*pointerToFunction)(double ) = NULL;
А это какая-то ерунда; если вы хотели так сделать указатель на filling , то писать надо double (*ptf)() = filling;
pointer_to_function ptf = filling; filling(); find_min_element(ptf);
Ваша функция требует передачи ей массива, а вы передаете ей указатель на функцию. И что ей с ним делать?
print(ptf);
Собственно, все, что от вас хотел преподаватель, я выложил вот тут (земенив только чтение массива заполнением случайными числами): http://ideone.com/w70pVj Вам нужно было передавать массив и его размер. Все. Так никаких глобальных переменных нет. Работать с указателями на функции можно (а иногда и нужно :)), но не в вашем случае.
Отслеживать
ответ дан 18 фев 2017 в 6:19
218k 15 15 золотых знаков 117 117 серебряных знаков 229 229 бронзовых знаков
Используйте std::vector вместо массива. Или же вместе с массивом передавайте его размер. В Вашем случае 10. Можно обойтись и без глобальных переменных и без указателей на функции. Функция sort_array возвращает 1 значения типа double a[10], которое выходит за пределы массива.filling - аналогично.
Отслеживать
ответ дан 18 фев 2017 в 6:18
4,030 1 1 золотой знак 10 10 серебряных знаков 19 19 бронзовых знаков
В вашей программе имеется несколько ошибок.
Функцию print правильно будет объявить, указав второй параметр - размер массива, так как в самой функции не возможно определить размер переданного ей массива в качестве аргумента, так как он неявно преобразуется в указатель на свой первый элемент. То есть в данном объявлении параметра функции
void print(double a[10]); ^^^^
число 10 не играет никакой роли, так как та же самая функция может быть объявлена с любым значением размера массива, который просто игнорируется в виду преобразования параметра массива в указатель на элемент массива. То есть данные объявления функций эквивалентны и объявляют одну и ту же функцию
void print(double a[100]); void print(double a[10]); void print(double a[]); void print(double *a);
Поэтому правильно будет определить функцию следующим образом
void print( const double a[], size_t n ) < for ( size_t i = 0; i < n; i++ ) < std::cout >
Можно объявить функцию с одним параметром. Но в этом случае тип параметра должен быть ссылкой на массив. Например
void print( const double ( &a )[10] ) < for ( size_t i = 0; i < 10; i++ ) < std::cout >
Или, если компилятор поддерживает цикл for на основе диапазона, то можно записать
void print( const double ( &a )[10] ) < for ( double x : a ) < std::cout >
Для функции find_min_element имеется точно такая же проблема с объявлением функции. Кроме того используется некая магическая константа, не понятно, откуда взявшаяся, использование которой может дать результат не тот, который вы ожидаете, так как при преобразовании к типу double может иметь место ее неточное представление.
К тому же почему-то последний элемент массива игнорируется
for (int i = 0; i < n - 1; i++) ^^^^^^^^^
Имеется стандартный алгоритм std::min_element , объявленный в заголовке , который выполняет задачу по поиску минимального элемента массива. Кроме того вы объявили тип возвращаемого значения функции как double в то время, как возвращаете индекс на минимальный элемент. Логичнее было бы, если бы возвращаемый тип значения функции был целочисленным. А иначе это вводит в заблуждение читающих ваш код, так как можно подумать, что возвращается не индекс минимального значения, а само минимальное значение.
size_t find_min_element( const double a[], size_t n ) < size_t min_i = 0; for ( size_t i = 1; i < n; i++ ) < if ( a[i] < a[min_i] ) < min_i = i; >> return min_i; >
Или если объявить первый параметр функции как ссылку на массив, то
size_t find_min_element( const double ( &a )[10] ) < size_t min_i = 0; for ( size_t i = 1; i < 10; i++ ) < if ( a[i] < a[min_i] ) < min_i = i; >> return min_i; >
В функции сортировки существует та же самая, описанная выше проблема с объявлением функции. Измените ее объявление, как это показано для других функций. Кроме того функция имеет неопределенное поведение, так как она возвращает из функции не существующий элемент массива. То есть идет обращение к памяти за пределами массива.
return a[n]; ^^^^^
Нет никакого смысла что-о возвращать из функции. Поэтому лучше объявить тип возвращаемого значения как Void . Например,
void sort_array( double a[], size_t n );
void sort_array( double ( &a )[10] );
В функции filling заполняется локальный массив, который прекратит свое существование после выхода из функции, и снова возвращается из функции несуществующий элемент локального массива. ТО есть функция имеет неопределенное поведение.
Измените ее объявление как
void filling( double a[], size_t n );
void filling( double ( &a )[10] ); double filling() < int i; double a[10]; int n = 10; cout > a[i]; > return a[i]; >
Судя по первому показанному сообщению об ошибке
Functions.cxx: In function ‘int main(int, char**)’: Functions.cxx:94:8: error: expected nested-name-specifier before ‘pointer_to_function’ using pointer_to_function = double(*)();
ваш компилятор не поддерживает объявление алиаса с использованием ключевого слова using .
Поэтому попробуйте заменить его на typedef объявление
typedef double( *pointer_to_function )();