КАК ВЕРНУТЬ МАССИВ ИЗ ФУНКЦИИ C
Для возврата массива из функции на языке C можно использовать указатели. Создайте массив внутри функции и верните указатель на него. В следующем примере показано, как это сделать:
const int SIZE = 5;
static int array[SIZE];
int* arr = createArray();
В этом примере функция createArray() создает массив array и заполняет его значениями от 0 до 4. Затем она возвращает указатель на этот массив. В функции main() этот указатель присваивается переменной arr и используется в цикле для вывода значений массива.

#31. Указатели на массивы — Язык C для начинающих
Передача массива в функцию. Как передать массив в функцию. C++ для начинающих. Урок #35.
Возврат нескольких значений функции через ссылки. Как вернуть несколько значений функции. Урок #52
Возврат нескольких значений функции через указатели. Функция возвращает несколько значений. #49
С++ 5. Передача одномерных и двумерных массивов в функцию
Поиск и подстановка по 2 критериям (ВПР по 2 столбцам)
#43. Указатели как параметры. Передача массивов в функции — Язык C для начинающих
C: Массивы
Тема массивов в С довольно обширна. В этом уроке мы познакомимся с базовыми концепциями работы с массивами.
Задание
Допишите функцию int sum(int *arr, length) , которая принимает массив и его размер и возвращает сумму элементов массива.
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Как развернуть массив c
В языке Си массивы и указатели тесно связаны. С помощью указателей мы также легко можем манипулировать элементами массива, как и с помощью индексов.
Имя массива без индексов в Си является адресом его первого элемента. Соответственно через операцию разыменования мы можем получить значение по этому адресу:
#include int main(void) < int array[] = ; printf("array[0] = %d", *array); // array[0] = 1 return 0; >
Прибавляя определенное число к имени массива, мы можем получить указатель на соответствующий элемент массива:
#include int main(void) < int array[] = ; int second = *(array + 1); // получим второй элемент printf("array[1] = %d", second); // array[1] = 2 return 0; >
Более того, когда мы в обращаемся к определенному элементу массива, используя квадратные скобки, например:
array[2]
компилятор рассмотривает эту запись как прибавление индекса к указателю на начальный элемент:
array+2
Поэтому мы даже можем написать 2[array] , что также будет валидным обращением к элементу массива:
#include int main(void) < int array[] = ; int third = 2[array]; printf("array[2] = %d", third); // array[2] = 3 return 0; >
Соответственно мы можем пробежаться по всем элементом массива, прибавляя к адресу определенное число:
#include int main(void) < int array[5] = ; for(int i = 0; i < 5; i++) < void* address = array + i; // получаем адрес i-го элемента массива int value = *(array + i); // получаем значение i-го элемента массива printf("array[%d]: address=%p \t value=%d \n", i, address, value); >return 0; >
То есть, например, адрес второго элемента будет представлять выражение a+1 , а его значение — *(a+1) .
Со сложением и вычитанием здесь действуют те же правила, что и в операциях с указателями. Добавление единицы означает прибавление к адресу значения, которое равно размеру типа массива. Так, в данном случае массив представляет тип int , размер которого, как правило, составляет 4 байта, поэтому прибавление единицы к адресу означает увеличение адреса на 4. Прибавляя к адресу 2, мы увеличиваем значение адреса на 4 * 2 =8. И так далее.
В итоге в моем случае я получу следующий результат работы программы:
array[0]: address=0060FE98 value=1 array[1]: address=0060FE9C value=2 array[2]: address=0060FEA0 value=3 array[3]: address=0060FEA4 value=4 array[4]: address=0060FEA8 value=5
В то же время имя массива это не стандартный указатель, мы не можем изменить его адрес, например, так:
int array[5] = ; array++; // так сделать нельзя int b = 8; array = &b; // так тоже сделать нельзя
Использование указателя для работы с массивом
Имя массива всегда хранит адрес самого первого элемента, соответственно его можно присвоить другому указателю и затем через указатель обращаться к элеиментам массива:
#include int main(void) < int array[5] = ; int *ptr = array; // указатель ptr хранит адрес первого элемента массива array printf("value: %d \n", *ptr); // 1 return 0; >
Прибавляя (или вычитая) определенное число от адреса указателя, можно переходить по элементам массива. Например, перейдем к третьему элементу:
#include int main(void) < int array[5] = ; int *ptr = array; // указатель ptr хранит адрес первого элемента массива array ptr = ptr + 2; // перемезаем указатель на 2 элемента вперед printf("value: %d \n", *ptr); // value: 3 return 0; >
Здесь указатель ptr изначально указывает на первый элемент массива. Увеличив указатель на 2, мы пропустим 2 элемента в массиве и перейдем к элементу array[2] .
И как и другие данные, можно по указателю изменить значение элемента массива:
#include int main(void) < int array[5] = ; int *ptr = array; // указатель ptr хранит адрес первого элемента массива array ptr = ptr + 2; // переходим к третьему элементу *ptr = 8; // меняем значение элемента, на который указывает указатель printf("array[2]: %d \n", array[2]); // array[2] : 8 return 0; >
Стоит отметить, что указатель также может использовать индексы, как и массивы:
#include int main(void) < int array[5] = ; int *ptr = array; // указатель ptr хранит адрес первого элемента массива array int value = ptr[2]; // используем индексы - получаем 3-й элемент (элемент с индексом 2) printf("value: %d \n", value); // value: 3 return 0; >
Строки и указатели
Ранее мы рассмотрели, что строка по сути является набором символов, окончанием которого служит нулевой символ ‘\0’. И фактически строку можно представить в виде массива:
char hello[] = "Hello METANIT.COM!";
Но в языке Си также для представления строк можно использовать указатели на тип char :
#include int main(void) < char *hello = "Hello METANIT.COM!"; // указатель на char - фактически строка printf("%s", hello); return 0; >
В данном случае оба определения строки — с помощью массива и указателя будут в равнозначны.
Перебор массива с помощью указателей
С помощью указателей легко перебрать массив:
int array[5] = ; for(int *ptr=array; ptr
Так как указатель хранит адрес, то мы можем продолжать цикл, пока адрес в указателе не станет равным адресу последнего элемента ( ptr
Аналогичным образом можно перебрать и многомерный массив:
#include int main(void) < int array[3][4] = < , , >; int n = sizeof(array)/sizeof(array[0]); // число строк int m = sizeof(array[0])/sizeof(array[0][0]); // число столбцов int *final = array[0] + n * m - 1; // указатель на самый последний элемент for(int *ptr=array[0], i = 1; ptr > return 0; >
Так как в данном случае мы имеем дело с двухмерным массивом, то адресом первого элемента будет выражение array[0] . Соответственно указатель указывает на этот элемент. С каждой итерацией указатель увеличивается на единицу, пока его значение не станет равным адресу последнего элемента, который хранится в указателе final.
Мы также могли бы обойтись и без указателя на последний элемент, проверяя значение счетчика, пока оно не станет равно общему количеству элементов (m * n):
for(int *ptr = array[0], i = 0; i < m*n;) < printf("%d \t", *ptr++); if(++i%m==0) < printf("\n"); >>
Но в любом случае программа вывела бы следующий результат:
1 2 3 4 5 6 7 8 9 10 11 12
String interning
Стоит отметить, что в языке Си для работы со строками применяется такой механизм как string interning или интернирование строк . В этом случае строки в виде строковых литералов сохраняются в приложении в секции .rodata (read-only data), которые предназначены для данных только для чтения, а строковые литералы рассматриваются как неизменяемые данные. Например, возьмем следующую программу:
#include char* str1 = «Hello»; char* str2 = «World»; int main(void)
Здесь определены две строки — str1 и str2, в функции main выводим адрес первого символа каждой из этих строк. Так, в моем случае я получу вывод:
str1 = 00007FF75E674000 str2 = 00007FF75E674006
По выводу видно, что первый символ второй строки расположен через 6 байтов начала первой строки. То есть строки расположены в памяти рядом друг с другом.
Но теперь сделаем строки одинаковыми:
#include char* str1 = «Hello World»; char* str2 = «Hello World»; int main(void)
Теперь вывод будет другим:
str1 = 00007FF75F674000 str2 = 00007FF75F674000
Оба адреса одинаковые, потому что обе переменных в реальности указывают на одну и ту же строку. Интернирование строк позволяет избежать дублирования строк, более эффективно использовать память. Причем здесь не важно, что переменные являются глобальными. Они также могут быть локальными, но все равно будут указывать на один и тот же адрес в .rodata .
#include int main(void)
Развертывание указателя массива в окне контрольных значений отладчика Visual C++
В этой статье описывается, как развернуть указатель массива для просмотра всех элементов массива в окне контрольных значений отладчика Visual C++.
Исходная версия продукта: Visual C++
Исходный номер базы знаний: 198953
Сводка
Начиная с Visual C++ версии 6.0, теперь можно развернуть указатель на массив, чтобы просмотреть все элементы массива в окне контрольных значений отладчика Visual C++. Эта функция не описана.
В окне Контроль введите выражение, которое вычисляет указатель, за которым следует запятая и количество элементов в массиве.
Дополнительная информация
- Создайте отладочную версию следующего кода в виде консольного приложения.
// Filename main.cpp // No compile option needed #include void main(void) < int * p; char* ptr = "Hello World"; p = new int [10]; for(int i=0; icout
Если вы хотите просмотреть определенный диапазон элементов, введите адрес первого элемента, чтобы указать начальный индекс, а затем описатель формата, как описано на предыдущих шагах. Например, (p+3),8 отображает элементы p[3..10] , а (ptr+3),10 — элементы ptr[3..12] . К сожалению, начальный индекс в окне контрольных значений будет [0], что фактически соответствует индексу 3 в этом примере. Помните, что смещение 3 необходимо добавить к каждому отображаемму индексу, чтобы получить фактический индекс элемента массива.
Обратная связь
Были ли сведения на этой странице полезными?