Структуры и функции


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

Рассмотрим использование структур в функциях на примере:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>

struct time
{
int hour;
int minute;
int second;
};

// прототип функции
struct time addminutes(struct time, int);

int main(void)
{
struct time current_time = {17, 38, 10};
int minutes = 21;

struct time result_time = addminutes(current_time, minutes);
printf("%d:%d:%d \n", result_time.hour, result_time.minute, result_time.second);

result_time = addminutes(current_time, 23);
printf("%d:%d:%d \n", result_time.hour, result_time.minute, result_time.second);

result_time = addminutes(current_time, 382);
printf("%d:%d:%d \n", result_time.hour, result_time.minute, result_time.second);
return 0;
}

struct time addminutes(struct time t, int minutes)
{
struct time result ={t.hour, t.minute, t.second};
int h, d;
// прибавляем минуты
result.minute += minutes;
// если минут больше 59, делим на 60
if(result.minute >=60)
{
h = result.minute / 60;
// от минут вычитаем 60 * h
result.minute -= 60 * h;
// к часам прибавляем h
result.hour +=h;
}
// если часов больше 23, делим на 24
if(result.hour >=24)
{
d = result.hour / 24;
// от часов вычитаем d * 24
result.hour -= 24 * d;
}
return result;
}
В начале программы определена структура time, которая представляет время и содержит три элемента для хранения значений для часов, минут и секунд.

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

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

Консольный вывод программы:

17:59:10
18:1:10
0:0:10
Указатели на структуру как параметры
При использовании структур в качестве параметров в функции следует учитывать, что при вызове функции для структуры, также как и для параметров типа int или char, выделяется память, в которую помещаются значения элементов структуры. То есть структура в функцию передается по значению, а это значит, что переданную в функцию структуру мы изменить не можем.

Для примера определим функцию, где попытаемся изменить структуру:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>

struct time
{
int hour;
int minute;
int second;
};

// прототип функции
void addminutes(struct time, int);

int main(void)
{
struct time current_time = {17, 38, 10};

addminutes(current_time, 21);
printf("In main \t %d:%d:%d \n", current_time.hour, current_time.minute, current_time.second);

return 0;
}

void addminutes(struct time t, int minutes)
{
int h, d;
// прибавляем минуты
t.minute += minutes;
// если минут больше 59, делим на 60
if(t.minute >=60)
{
h = t.minute / 60;
// от минут вычитаем 60 * h
t.minute -= 60 * h;
// к часам прибавляем h
t.hour +=h;
}
// если часов больше 23, делим на 24
if(t.hour >=24)
{
d = t.hour / 24;
// от часов вычитаем d * 24
t.hour -= 24 * d;
}
printf("In addminutes \t %d:%d:%d \n", t.hour, t.minute, t.second);
}
Если мы запустим программу, то увидим передаваемая структура current_time в функцию addminutes после выполнения этой функции не изменится:

In addminutes 17:59:10
In main 17:38:10
Если мы действительно хотим изменить структуру в функции, то на надо передавать не саму структуру, а указатель на нее:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>

struct time
{
int hour;
int minute;
int second;
};

// прототип функции
void addminutes(struct time *, int);

int main(void)
{
struct time current_time = {17, 38, 10};
struct time * p_time = &current_time;
addminutes(p_time, 21);
printf("In main \t %d:%d:%d \n", current_time.hour, current_time.minute, current_time.second);

return 0;
}

void addminutes(struct time *t, int minutes)
{
int h, d;
// прибавляем минуты
t->minute += minutes;
// если минут больше 59, делим на 60
if(t->minute >=60)
{
h = t->minute / 60;
// от минут вычитаем 60 * h
t->minute -= 60 * h;
// к часам прибавляем h
t->hour +=h;
}
// если часов больше 23, делим на 24
if(t->hour >=24)
{
d = t->hour / 24;
// от часов вычитаем d * 24
t->hour -= 24 * d;
}
printf("In addminutes \t %d:%d:%d \n", t->hour, t->minute, t->second);
}
Теперь в функцию передается указатель на структуру p_time, который содержит адрес структуры current_time. В итоге любое изменение значений по этому указателю приведет к изменению самой структуры current_time. И результаты программы будут уже отличаться:

In addminutes 17:59:10
In main 17:59:10
Указатели на структуру как результаты функций
И еще один вариант использования структур в функции - это возвращение из функции указателя на структуру. Например, определим функцию, которая будет возвращать указатель на структуру time:

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
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <stdlib.h>

struct time
{
int hour;
int minute;
int second;
};

// прототип функции
struct time * input(void);

int main(void)
{
struct time * p_time = input();
printf("%d:%d:%d \n", p_time->hour, p_time->minute, p_time->second);

free(p_time); // освобождаем память
return 0;
}

struct time * input()
{
// выделяем память для структуры
struct time * p_time = (struct time *) malloc(sizeof(struct time));
// ввод значений
printf("Enter hour: ");
scanf("%d", &p_time->hour);
printf("Enter minutes: ");
scanf("%d", &p_time->minute);
printf("Enter seconds: ");
scanf("%d", &p_time->second);

return p_time;
}
В функции input вначале выделяем память для структуры, получая указатель на выделенный блок памяти.

Потом поочередно вводим значения для элементов структуры и возвращаем указатель из функции.

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

Консольный вывод программы:

Enter hour: 22
Enter minutes: 14
Enter seconds: 18
22:14:18