Перейти к содержимому

Как вернуть указатель из функции c

  • автор:

Как вернуть указатель из функции c

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

// пример некорректного возвращения значения int* max(int a, int b) < if (a >b) return &a; else return &b; >

Параметры функции аналогичны переменным — при вызове функции в стеке для них выделяется память. И вданном случае возвращается адрес участка памяти соответствующего параметра ( return &a или return &b ). Но после возвращения адреса функция завершает свою работу, соответствующие участки памяти очищаются, параметры удаляются, поэтому возвращенный адрес будет недействительным. И хотя компилятор даже может скомпилировать данную функцию, ограничившись предупреждениями, но такая функция не будет работать корректно.

Тем не менее это не значит, что мы в принципе не можем возвращать указатель из функции. Например, возьмем следующую ситуацию:

#include int* max(int*, int*); int main() < int n; int m; int* ptr = max(&n, &m); std::cout // пример корректного возвращения значения int* max(int *a, int *b) < if (*a >*b) // разыменовываем указатели return a; else return b; >

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

При этом нам необязательно присваивать результат переменной или константе, можно напрямую обратиться к результату функции:

int main() < int n; int m; std::cout 

Возвращение ссылки

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

// пример некорректного возвращения ссылки int& max(int a, int b) < if (a >b) return a; else return b; >

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

Чтобы выйти из ситуации, мы можем передавать значения по ссылке:

#include int& max(int&, int&); int main() < int n; int m; int result = max(n, m); std::cout // пример корректного возвращения ссылки int& max(int& a, int& b) < if (a >b) return a; else return b; >

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

#include const int& max(const int&, const int&); int main() < int n; int m; int result = max(n, m); std::cout // пример корректного возвращения ссылки const int& max(const int& a, const int& b) < if (a >b) return a; else return b; >

Как вернуть указатель из функции c

Доброго дня изучаю С++ пару дней помогите разьяснить нюанс, как понимаю функция не может вернуть массив, но может вернуть указатель на массив. Пытаюсь реализовать не оплучается. Задача пользователь вводит число - число передается в функцию, функция образует массив из 5 элементов где каждое число на 3 больше предыдущего, начиная с параметра функции. Собственно код, но что то не то

int *byThress(int i); int _tmain(int argc, _TCHAR* argv[]) < int i,k; int *p; cout > i; cout int *byThress(int i) < int k ; int *p; int mas[5]; mas[0] = i; for(k=1;k<5;k++) mas[k]=mas[k-1]+3; return mas;
Neolit1819
Посмотреть профиль
Найти ещё сообщения от Neolit1819

Лжец и смутьян
Форумчанин
Регистрация: 03.04.2009
Сообщений: 194

const stdsize = 5; const stdinc = 3; void GenArray(int, int, int, int*); int main() < int v; cout > v; cout void GenArray(int value, int inc, int size, int* result)

Помогли тебе - помоги другому.
Форумчанин
Регистрация: 29.09.2010
Сообщений: 636
ну как вариант

int *GenArray(int value, int inc, int size, int* result) . return result;

оно и изменит массив и в добавок и вернет указатель.
многие стандартные функции так поступают для удобства, например memmove, strcpy.

Пользователь
Регистрация: 28.03.2011
Сообщений: 51
Сообщение от Alt

const stdsize = 5; const stdinc = 3; void GenArray(int, int, int, int*); int main() < int v; cout > v; cout void GenArray(int value, int inc, int size, int* result)

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

Последний раз редактировалось Neolit1819; 28.03.2011 в 12:56 .

Neolit1819
Посмотреть профиль
Найти ещё сообщения от Neolit1819

Возврат указателя на функцию

Чтобы вернуть указатель на функцию, можно использовать следующие способы.

1) Явное указание типа.

void (*f1())(char)

2) Объявление синонима типа через typedef .

typedef void (*TFunc)(char); TFunc f1()

3) Объявление синонима типа через using ( c++11 ).

using TFunc = void (*)(char); TFunc f1()

4) Полуавтоматическое определение возвращаемого типа ( c++11 ).

auto f1() -> decltype(&f0)

5) Автоматическое определение возвращаемого типа ( c++14 ).

auto f1()

Отслеживать
23.8k 3 3 золотых знака 47 47 серебряных знаков 61 61 бронзовый знак
ответ дан 1 дек 2015 в 7:16
user194374 user194374

Нашел ответ на англоязычном SO.

В вашем случае правильное определение для f1 будет:

void (*f1())(char)

В общем случае сигнатура должна быть такая:

возвращаемое_значение_возвращаемой_функции (*имя_функции(типы_параметров_функции))(типы_параметров_возвращаемой_функции); 

Вообще, не рекомендую использовать такой синтаксис, т.к. сигнатура получается нечитаемой. Лучше создать аллиас на возвращаемый тип с помощью using или typedef :

using Function = void (*)(char); Function f1()

Язык Си. Вернуть указатель на выделенную память malloc() на массив указателей типа char через аргументы функции

Вопрос звучит так: как можно вернуть через аргумент функции адрес выделенной памяти malloc на массив указателей типа char.

#include #include #include void test(char*** m, char** s, int n) < *m = (char**)malloc(n * sizeof(char*)); for (int i = 0; i < n; ++i) < char* d = (char*)malloc(6); strcpy(d, s ); (*m) = d; > for (int i = 0; i < n; ++i) printf("%s -- >%p\n", (*m) , (*m) ); > int main(void) < char** j = NULL; int n = 3; char* s[] = "test", "test1", "test3">; test(&j, s, n); if (j != NULL) < for (int i = 0; i < n; ++i) < printf("%s -- >%p\n", j , j ); free(j ); > free(j); > return 0; >

Похожие статьи

  • Передача параметров по ссылке и по указателю
  • Использование нетипизированного указателя для передачи массива
  • Можно ли как-то без непосредственного явного указания функции сделать указатель на функцию?

Возврат указателей

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

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

Ниже показана функция, возвращающая указатель на строку в месте, где найдено соответствие символов:

char *match(char с, char *s)
register int count;
count = 0;
while(c!=s[count] && s[count]) count++;
return(&s[count]);
>

Функция match() пытается вернуть указатель на позицию в строке, где первый раз найден символ с. Если не найдено соответствие, возвращается указатель, содержащий NULL. Ниже показана небольшая программа, использующая match():

char *match(char c*, char *s);

int main(void)
char s[80], *p, ch;
gets (s) ;
ch = getche();
p = match(ch, s);
if (p) /* совпадение */
printf("%s ", p);
else
printf("No match found.");
return 0;
>

Данная программа осуществляет чтение строки, а затем символа. Если символ содержится в строке, то выводится строка, начиная с момента совпадения. Иначе выводится «No match found».

Язык Си. Вернуть указатель на выделенную память malloc() на массив указателей типа char через аргументы функции

Вопрос звучит так: как можно вернуть через аргумент функции адрес выделенной памяти malloc на массив указателей типа char.

#include #include #include void test(char*** m, char** s, int n) < *m = (char**)malloc(n * sizeof(char*)); for (int i = 0; i < n; ++i) < char* d = (char*)malloc(6); strcpy(d, s ); (*m) = d; > for (int i = 0; i < n; ++i) printf("%s -- >%p\n", (*m) , (*m) ); > int main(void) < char** j = NULL; int n = 3; char* s[] = "test", "test1", "test3">; test(&j, s, n); if (j != NULL) < for (int i = 0; i < n; ++i) < printf("%s -- >%p\n", j , j ); free(j ); > free(j); > return 0; >

Похожие статьи

  • Передача параметров по ссылке и по указателю
  • Использование нетипизированного указателя для передачи массива
  • Можно ли как-то без непосредственного явного указания функции сделать указатель на функцию?

вернуть указатель на двумерный массив

Здравствуйте уважаемые сишники. Имеется несколько статических двумерных массивов, все M x N. Как записать тип функции, которая вернет указатель на один из этих массивов? Очень не хочется переделывать на char**.

Aswed ★★★★★
18.02.14 22:53:09 MSK

Ctrl+A Backspace Ctrl+S Alt+F4

templarrr ★★★★★
( 18.02.14 22:55:04 MSK )

которая вернет указатель на один из этих массивов?

Может всё-таки на первый элемент?

ziemin ★★
( 18.02.14 22:55:56 MSK )

static int v[M][N], u[M][N]; int (*f(void))[M][N]

Функция f возвращает указатель на двумерный массив.

anonymous
( 18.02.14 23:03:45 MSK )
Ответ на: комментарий от anonymous 18.02.14 23:03:45 MSK
Aswed ★★★★★
( 18.02.14 23:11:03 MSK ) автор топика

в Сях(«обычных») не гарантируется проверка выхода за границу массива и даже ожидается , что таковой нет во строенных синтаксических конструкциях.

то, что нарисовал анонимус лиш «коментарий» чека на проверку что это именно прямоугольный MxN , а не вектор M*Nx1 , а не вектор 1*M*N, а ли ещё какой вариант прямоуголизации числа MxN «обычный С-компилятор» делать не обязан и как правило таковы реализации.

вообщем хоть и стёб но Брайан Керниганом:

«Почему Паскаль не является моим любимым языком программирования"

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

qulinxao ★★☆
( 19.02.14 08:55:52 MSK )

Имеется несколько статических двумерных массивов, все M x N.

в PureC не бывает многомерных массивов. Бывают массивы массивов. Ты про них?

если да, то у меня для тебя плохие новости: невозможно вернуть массив изх функции. Можно только указатель.

только так можно:

#include void print_matrix(int matrix[][3]) < int j, k; for(j = 0; j < 3; j++, printf("\n")) for(k = 0; k < 3; k++) printf("%d ", matrix[j][k]); >void gen_matrix1(int matrix[][3]) < int j, k; for(j = 0; j < 3; j++) for(k = 0; k < 3; k++) matrix[j][k] = (j==k ? 1 : 0); >int main()

Возврат указателя на функцию

Чтобы вернуть указатель на функцию, можно использовать следующие способы.

1) Явное указание типа.

void (*f1())(char)

2) Объявление синонима типа через typedef .

typedef void (*TFunc)(char); TFunc f1()

3) Объявление синонима типа через using ( c++11 ).

using TFunc = void (*)(char); TFunc f1()

4) Полуавтоматическое определение возвращаемого типа ( c++11 ).

auto f1() -> decltype(&f0)

5) Автоматическое определение возвращаемого типа ( c++14 ).

auto f1()

Отслеживать
23.8k 3 3 золотых знака 47 47 серебряных знаков 61 61 бронзовый знак
ответ дан 1 дек 2015 в 7:16
user194374 user194374

Нашел ответ на англоязычном SO.

В вашем случае правильное определение для f1 будет:

void (*f1())(char)

В общем случае сигнатура должна быть такая:

возвращаемое_значение_возвращаемой_функции (*имя_функции(типы_параметров_функции))(типы_параметров_возвращаемой_функции); 

Вообще, не рекомендую использовать такой синтаксис, т.к. сигнатура получается нечитаемой. Лучше создать аллиас на возвращаемый тип с помощью using или typedef :

using Function = void (*)(char); Function f1()

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *