Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.78/40: Рейтинг темы: голосов - 40, средняя оценка - 4.78
-6 / 22 / 7
Регистрация: 16.12.2016
Сообщений: 716
1

Возврат строки из функции

02.02.2017, 10:04. Показов 7891. Ответов 5
Метки нет (Все метки)

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

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.02.2017, 10:04
Ответы с готовыми решениями:

Передача строки в функцию и возврат строки как результата
Короче товарищи замучился я со строками в си, поскольку перешел из delphi там с этим проблем нет. И...

Возврат строки из функции
//char perfomers; //char _perfomers; char GetPerfomers(){strcpy(_perfomers,perfomers);return...

Возврат строки из функции
Всем привет. Написал следуюущую фунцию для генерации рандомных строк : LPWSTR RandomString(int...

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

5
6014 / 2136 / 744
Регистрация: 10.12.2010
Сообщений: 5,979
Записей в блоге: 3
02.02.2017, 10:31 2
Цитата Сообщение от SadiQ228 Посмотреть сообщение
а как тогда int значения возвращаются?
Путем копирования значения. Глянем на пример:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
int foo(void)
{
  int a = 200;
  a++;
  a += 4;
  return a;
}
 
void bar(void)
{
  int k = foo();
  k++;
}
В общем случае будет сгенерирован следующий код:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
foo():
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 200
        add     DWORD PTR [rbp-4], 1
        add     DWORD PTR [rbp-4], 4
        mov     eax, DWORD PTR [rbp-4]
        pop     rbp
        ret
bar():
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        call    foo()
        mov     DWORD PTR [rbp-4], eax
        add     DWORD PTR [rbp-4], 1
        nop
        leave
        ret
Тут по этой части два места: возврат значения из функии и запись в переменную на стороне вызова. Тут есть стадии:
1) запись возвращаемого значения в регистр eax инструкцией
Assembler
1
mov     eax, DWORD PTR [rbp-4]
2) передача управления обратно на сторону вызова (возврат в функцию bar()) с помощью инструкций
Assembler
1
2
pop     rbp
ret
3) получение значения из регистра и запись его в переменную k
Assembler
1
mov     DWORD PTR [rbp-4], eax
Со строками так не сделать, потому что они, очевидно, не влезают в регистр, да и вообще не являются самостоятельным типом данных в принципе, а массивом. Поэтому, раз в регистр не записать, то надо все же куда-то это сделать, чтобы все таки вернуть. Есть два концептуально разных подхода (покажу кодом):
Раз:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const char* foo(void)
{
  // строка как угодно может быть задана
  #define STRING "We will return this string from function!"
  const char* s = malloc(strlen(STRING) + 1); // память через которую мы простаскиваем строку
  strcpy(s, STRING); // пишем в нее
  #undef STRING
  return s;
}
 
void bar(void)
{
  const char* temp = foo();
  char receivedString[256];
  strcpy(receivedString, temp); // читаем из памяти
  free(temp);
}
Два:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const char* foo(void)
{
  static char buffer[256]; // память через которую мы простаскиваем строку
  #define STRING "We will return this string from function!"
  strcpy(buffer, STRING);
  #undef STRING
  return (const char*)&buffer[0];
}
 
void bar(void)
{
  char* temp = foo();
  char receivedString[256];
  strcpy(receivedString, temp); // читаем из памяти
}
P.S. про ассемблер: в ресерче таких вопросов очень хорошо помогает штука http://gcc.godbolt.org/ ибо для людей, слабо разбирающихся в ассемблере, подсвечивает соответствующие участки одного и второго кода. Наглядно видно что где.
1
-6 / 22 / 7
Регистрация: 16.12.2016
Сообщений: 716
02.02.2017, 10:33  [ТС] 3
простейший пример, когда работаем на микроконтроллере например, то борьба за память не шуточная, и иницилизировать переменные лишние ( пусть и строковые) жалко лишний раз, хочется вернуть строку ту же самую, модифицированную

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#define MAX 100
void lower (char buf[], char str[]);
int main()
{
  int i;
  char buf [MAX];
  char str [MAX];
  for (i=0;i<MAX;i++){
      str[i]='\0';
      buf[i]='\0';
    }
  printf("Введите строку: ");
  scanf("%s", &buf);
  lower (buf, str);
  printf("low: %s\n",str);
  return 0;
}
void lower (char buf[], char str[])
{
  int i,j;
  for(i=0,j=0; i<MAX; i++,j++){
      str[j] = (buf[i]>='A'&&buf[i]<='Z') ? buf[i]+'a'-'A' : buf[i];
    }
}
Добавлено через 58 секунд
Большое спасибо за развернутый ответ интересно почитать!
я пока к сожалению не проходил еще ни память ни маллоки) но уже близок к этому скоро буду делать)
1
Эксперт C
26073 / 16263 / 3494
Регистрация: 24.12.2010
Сообщений: 35,642
02.02.2017, 11:13 4
Цитата Сообщение от SadiQ228 Посмотреть сообщение
C
1
2
3
4
for (i=0;i<MAX;i++){
* * * str[i]='\0';
* * * buf[i]='\0';
* * }
Эквивалент
C
1
2
memset(str, 0, MAX);
memset(buf, 0, MAX);
Добавлено через 6 минут
C
1
2
3
4
5
6
7
void lower (char *buf, char *str)
{
  int i;
  for(i=0; i<MAX; i++){
      str[i] = (buf[i]>='A'&&buf[i]<='Z') ? buf[i]+'a'-'A' : buf[i];
  }
}
Или
C
1
2
3
4
5
6
7
void lower (char buf[], char str[])
{
  int i;
  for(i=0; i<MAX; i++,buf++, str++){
      *str = (*buf>='A' && *buf<='Z') ? *buf+'a'-'A' : *buf;
  }
}
2
959 / 699 / 228
Регистрация: 30.06.2015
Сообщений: 3,746
Записей в блоге: 37
02.02.2017, 11:41 5
Цитата Сообщение от SadiQ228 Посмотреть сообщение
простейший пример, когда работаем на микроконтроллере например, то борьба за память не шуточная,
В этом случае нужно обьявить строковый масив глобальным, и все дела. Ничего тормозить не будет. Не будет при обращении к функции заново создаваться новый массив.
0
Эксперт C
26073 / 16263 / 3494
Регистрация: 24.12.2010
Сообщений: 35,642
02.02.2017, 11:48 6
Цитата Сообщение от CoderHuligan Посмотреть сообщение
обьявить строковый масив глобальным,
Не камильфо, конечно. Но если
Цитата Сообщение от SadiQ228 Посмотреть сообщение
борьба за память не шуточная,
тут не до причесок. Всетки по возможности лучше static, чтобы в других исходниках о нем не думать.
Цитата Сообщение от CoderHuligan Посмотреть сообщение
Не будет при обращении к функции заново создаваться новый массив.
А он и так не создается. В стеке создается пара указателей, но это уж совсем ерунда.
2
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.02.2017, 11:48

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

Возврат c-style строки из функции
Здравствуйте, пытаюсь решить задачу на степике, но не получается. Поэтому воспользовался Qt и...

Возврат каретки и перевод строки в приглашении Командной строки
В строке приглашения MS-DOS после вывода всей информации перейти на новую строчку. как это сделать?

Возврат 2 значений из функции с одним вызовом этой же функции
Вообщем где то в какой то игре была хукнута одна функция int function(int arg1,int arg2,int...

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

Возврат функции
Не могу сообразить как в этом коде Страуструпа указать возврат функции return, чтобы выполнились...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.