Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Материалы для подготовки к экзамену по ОП.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
298 Кб
Скачать
☆

Передача аргументов По значению

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

#include <conio.h>

#include <stdio.h>

void change(int a) {

a = 100;

printf("%d\n", a);

}

void main() {

int d = 200;

printf("%d\n", d);

change(d);

printf("%d", d);

getch();

}

Программы выведет

200

100

200

Понятно почему. Внутри функции мы работаем с переменной «а», которая является копией переменной «d». Мы изменяем локальную копию, но сама переменная d при этом не меняется. После выхода из функции локальная переменная будет уничтожена. Переменная d при этом никак не изменится.

По указателю (ссылке)

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

#include <conio.h>

#include <stdio.h>

void change(int *a) {

*a = 100;

printf("%d\n", *a);

}

void main() {

int d = 200;

printf("%d\n", d);

change(&d);

printf("%d", d);

getch();

}

Вот теперь программа выводит

200

100

100

Здесь также была создана локальная переменная, но так как передан был адрес, то мы изменили значение переменной d, используя её адрес в оперативной памяти.

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

#include <conio.h>

#include <stdio.h>

#include <stdlib.h>

void init(int *a, unsigned size) {

a = (int*) malloc(size * sizeof(int));

}

void main() {

int *a = NULL;

init(a, 100);

if (a == NULL) {

printf("ERROR");

} else {

printf("OKAY...");

free(a);

}

getch();

}

Но эта функция выведет ERROR. Мы передали адрес переменной. Внутри функции init была создана локальная переменная a, которая хранит адрес массива. После выхода из функции эта локальная переменная была уничтожена. Кроме того, что мы не смогли добиться нужного результата, у нас обнаружилась утечка памяти: была выделена память на куче, но уже не существует переменной, которая бы хранила адрес этого участка.

Для изменения объекта необходимо передавать указатель на него, в данном случае – указатель на указатель.

#include <conio.h>

#include <stdio.h>

#include <stdlib.h>

void init(int **a, unsigned size) {

*a = (int*) malloc(size * sizeof(int));

}

void main() {

int *a = NULL;

init(&a, 100);

if (a == NULL) {

printf("ERROR");

} else {

printf("OKAY...");

free(a);

}

getch();

}

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

#include <conio.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

char* initByString(const char *str) {

char *p = (char*) malloc(strlen(str) + 1);

strcpy(p, str);

return p;

}

void main() {

char *test = initByString("Hello World!");

printf("%s", test);

free(test);

getch();

}

В этом примере утечки памяти не происходит. Мы выделили память с помощью функции malloc, скопировали туда строку, а после этого вернули указатель. Локальные переменные были удалены, но переменная test хранит адрес участка памяти на куче, поэтому можно его удалить с помощью функции free.