Работа с массивами в языке Си
На этой странице относительно подробно рассказывается о статических и динамических массивах. Краткое изложение основных моментов и описание методов поиска ошибок доступны при нажатии на кнопки выше. Двумерные массивы описаны на этой странице.
Массив – это линейно упорядоченная совокупность однотипных элементов. Массив определяется типом элементов (int, double, . ) и длиной. Доступ к элементам осуществляется по индексу – порядковому номеру элемента массива. Логически первый элемент массива имеет индекс ноль. В языке Си существуют статические массивы, число элементов в которых должно быть известно в момент компиляции программы, и динамические массивы, размер которых задается в процессе выполнения программы, то есть может зависеть от входных данных. Эти два типа отличаются только методом создания массива, поэтому сначала рассмотрим статические массивы.
Статические массивы
Способы объявления статических массивов
Объявление статического массива отличается от объявления обычной переменной только указанием количества элементов массива. Например, следующее объявление означает, что именем points называется массив из 100 действительных чисел.
double points[100];
В некотором смысле можно считать, что такое объявление переменной points создает 100 переменных, которые называются points[0], points[1], . points[99]. Плюс к этому, «имена» этих переменных можно вычислять: points[1], points[0+1] или points[k-1] имеют одно значение (если k=2).
В реальных программах следует избегать явного использования числовых констант в объявлениях массива (и других частях программы). Если нам нужно объявить два массива, которые теоретически могут иметь разный размер, например,
double points[100]; int students[100];
то в дальнейшем, если возникнет необходимость увеличить один из массивов, будет сложно отличить одну константу от другой. Особенно это верно при обработке элементов массива (см. ниже). Правильным считается использование директив препроцессора для присвоения константам «говорящих» имен. Например:
#define NPOINTS 100 #define NSTUDENTS 100 . double points[NPOINTS]; int students[NSTUDENTS];
Объявление массива может быть совмещено с присвоением значений его элементам. Например,
double points[] = ;
создает массив из четырех действительных чисел с указанными значениями. Заметим, что в данном случае число элементов массива в квадратных скобках не указывается. Компилятор самостоятельно вычисляет длину по списку начальных значений. В программе можно вычислить длину такого массива, разделив его размер на размер одного элемента (пример ниже).
Работа с элементами массива
Для доступа к элементу массива достаточно знать его имя и порядковый номер элемента. В языке Си элементы массива индексируются начиная с нуля, то есть в массиве из двух элементов корректными являются индексы 0 и 1. Если массив имеет имя array, то его k -й элемент записывается как array[k] . Это выражение может использоваться как для получения значения элемента массива, так и для его изменения, если оно стоит в левой части оператора присваивания. Рассмотрим для примера следующую программу.
#define NPOINTS 100 int main() < double points[NPOINTS]; int k; points[0] = 0.1; for(k=1; k < NPOINTS; k++) < points[k] = 0.1 + points[k-1]; >return 0; >
Эта программа заполняет массив действительных чисел значениями 0, 0.1, 0.2 и так далее. Отметим, что макропеременная NPOINTS используется как при объявлении массива, так и в качестве верхней границы цикла по всем его элементам. Если размер массива нужно будет изменить, то достаточно исправить одну строчку в программе (#define).
Пример работы с массивом, который задан с начальными значениями:
int main() < double points[] = ; int k; int npoints = sizeof(points)/sizeof(points[0]); for(k=0; k < npoints; k++) < printf("points[%d] = %lf\n", k, points[k]); >return 0; >
Типичная ошибка при работе с массивами состоит в указании неправильного индекса. Если в приведенной выше программе переменная цикла k будет пробегать значения от 0 до npoints включительно, то поведение программы, вообще говоря, может быть любым. Наиболее вероятным поведением является вывод на экран какого-то значения, но может возникнуть и критическая ошибка, которая приведет к аварийной остановке программы.
Представление массива в памяти и адресная арифметика
В памяти ЭВМ элементы массива записаны последовательно без пропусков. Имя массива является указателем на его начальный элемент (с индексом 0). Поскольку в массиве все элементы имеют одинаковый тип, то зная адрес начала массива (A), размер одного элемента (size) и индекс k можно вычислить адрес размещения k-ого элемента: A + k*size. Если требуется получить значение k-ого элемента массива, то достаточно выполнить одно умножение (k*size), одно сложение (A + k*size) и загрузить значение из памяти по только что вычисленному адресу. Таким образом, обращение к элементу массива очень эффективно и сложность этой операции не зависит от величины индекса k: получение (или изменение) значения нулевого элемента столь же эффективно, как и миллионного.
Хорошо, адрес начала массива мы знаем — это его имя, индекс нам известен, но как узнать size (размер одного элемента)? Чуть ниже мы узнаем как это сделать, но для работы с указателями на элементы массива это не требуется! В языке Си к указателям можно прибавлять целые числа. Например, если есть указатель double *a; , то значением выражения a+9 будет адрес десятого (еще раз вспомним, что массивы индексируются с нуля!) элемента массива, который начинается с адреса a . Компилятор сам понимает, что a является указателем на double и прибавляет нужное значение.
Обратной стороной последовательно хранения элементов в памяти является сложность вставки нового значения с сохранением порядка следования элементов. Например, если в массив нужно добавить новое значение по индексу 0, то чтобы «освободить» место все элементы массива придется сдвинуть на одну позицию. Ясно, что сложность этой операции зависит от длины массива. Чем больше длина, тем дольше выполняется это действие.
Передача массива в функцию
Функция может получать на вход массив. В действительности в функцию передается адрес начала массива и его длина. Прототип функции может быть оформлен либо так:
int print_array(double x[], int len);
int print_array(double *x, int len);
Эти варианты являются эквивалентными. Некоторые программисты предпочитают первый (квадратные скобки показывают, что формальный параметр функции является массивом), другие — второй (имя массива является указателем на нулевой элемент). Естественно, что функция может иметь и другие параметры, в том числе, другие массивы. Это только пример.
Рассмотрим возможную реализацию функции распечатывания массива.
#include int print_array(double x[], int len) < int k; for(k = 0; k < len; k++) < printf("x[%d] = %lf\n", k, x[k]); >return 0; >
При вызове функции в качестве аргумента нужно передавать имя массива и его длину.
int main() < double points[] = ; int npoints = sizeof(points)/sizeof(points[0]); print_array(points, npoints); return 0; >
Внимание! Если функция print_array изменит значение элемента массива x (например, в цикле будет написано x[k]=0; ), то изменятся значения и в массиве points функции main. Элементы массива при вызове функций не копируются! Функция получает на вход адрес памяти, где записаны элементы массива. Эта память «общая» для вызывающей и вызываемой функции.
Динамические массивы: malloc и free
Статические массивы имеют одно существенное ограничение: размер массива должен быть известен в момент компиляции программы. В большинстве задач размер данных становится известным только в момент выполнения программы. Например, вы написали программу для обработки списка друзей или подписчиков в социальной сети. У одного пользователя друзей мало, а у другого — очень много. Какое значение выбрать для длины массива друзей? 200? 1000? Миллион? Если константа будет очень большой, чтобы «заведомо» (посмотрите как росло число пользователей Интернет) устраивать всех пользователей, то для подавляющего числа пользователей это приведет к излишним затратам памяти. Захотите ли Вы поставить на свой телефон программу, которая при запуске займет всю его память с сообщением: «А вдруг у тебя миллион друзей. Нет? Всего 12?! Неплохо, прямо как у Oушена! А y Трампа миллион. «? [Друзей не должно и не может быть так много, но это к делу не относится.] Чтобы избежать таких ситуаций нужно уметь выделять минимально необходимое количество памяти.
- выделение памяти под массив;
- освобождение памяти, когда она больше не требуется.
Стандартная библиотека языка Си содержит несколько функций для работы с динамической памятью. Нам понадобятся две: malloc (memory allocation — выделение памяти) и free (освобождение). Для использования этих удивительных функций нужно в программе подключить заголовочный файл . Пример программы приведен ниже. Сначала посмотрим, что делают эти функции.
malloc: динамическое выделение памяти
Прототип: void *malloc(size_t size); Параметры: size — беззнаковое целое число, размер запрашиваемой памяти в байтах. Возвращает: Адрес начала выделенной памяти или NULL, если не удалось выделить память. Функция malloc возвращает указатель типа void * — это «абстрактный» указатель на память, который может быть приведен к указателю на любой тип. Функция malloc не может сразу возвращать указатель нужного типа, так как она используется для создания разных массивов, а в прототипе нужно указать конкретный тип возвращаемого значения.
Для выделения памяти под массив из n элементов типа T, где в T могут быть стандартные типы int , double и т.п., необходимо знать размер значения T в байтах. Для определения этой величины в языке Си есть специальный оператор sizeof , который в момент компиляции программы вычисляет нужное значение. Например, массив из n целых чисел будет занимать n*sizeof(int) байт памяти.
Таким образом, для создания динамического массива некоторого типа, например с массива целых чисел, нужно использовать команду вида:
int length; int *points; // . получили значение length (длина массива) points = (int *)malloc(length * sizeof(int));
Если нужен другой тип данных, допустим double , то int заменяется на нужное имя ( double ) в трех местах (кроме первой строки, так как длина массива всегда является целым числом).
free: освобождение памяти
Функция free позволяет освободить область памяти, которая ранее была выделена программе при вызове malloc .
Прототип void free(void *ptr); Параметры: ptr — указатель, который был получен в результат вызова malloc.
В качестве аргумента функции free может использоваться только тот адрес, который был получен в результате вызова malloc. Нельзя создать статический массив и «освободить» его функцией free. Адрес может быть освобожден только один раз. Если два раза подряд вызвать функцию free с одним и тем же аргументом, то это приведет к аварийному завершению программы.
Пример программы с динамическим массивом
В качестве иллюстрации описанных методов рассмотрим программу, которая динамически выделяет память под массив и считывает его.
#include #include int main() < int npoints; double *points; int k; scanf("%d", &npoints); /* npoints получает значение в момент выполнения программы */ points = (double *)malloc(npoints*sizeof(double)); /* Выдели память для хранения npoints элементов, каждый размера sizeof(double) */ if(points == NULL) < printf("Произошла ошибка. Запросили слишком много памяти??\n"); return -1; >/* Считываем данные с использованием адресной арифметики */ k = 0; while(k < npoints && scanf("%lf", points+k) == 1) < k++; >/* Работаем с points как с обычным массивом */ /* Например, вызываем функцию print_array(points, npoints) */ free(points); /* Освободили память */ return 0; >
Функции, которые возвращают массив
Иногда бывает удобно сделать функцию, которая возвращает динамически созданный массив. Примером может служить функция считывания массива из файла. Такая функция может получать на вход файловую переменную ( FILE * ) и должна вернуть в вызывающую функцию массив значений. Например, массив действительнах чисел. Попробуем ее реализовать.
Во-первых, нужно понять, какой прототип должна иметь такая функция. Она должна вернуть два значения: адрес выделенной памяти и длину массива. Как мы уже знаем, несколько значений можно вернуть используя указатели. Длина массива имеет тип int . Значит параметр функции будет иметь тип int * (адрес, по которому нужно записать значение). Массив — это адрес нулевого элемента, то есть double * . Значит параметр будет иметь тип double ** — «указатель на указатель». Мы должны передать адрес (одна звездочка), по которому нужно записать результат вызова malloc, который имеет тип double * . В результате получаем следующий прототип:
int read_array(FILE *input, double **array, int *length);
Собственно возвращаемое значение функции ( int ) может быть кодом ошибки. Если функция вернет 0, то это означает успешное выполнение. Любое ненулевое значение означает ошибку.
Теперь можно рассмотреть структуру тела функции (для наглядности в приведенном ниже коде отсутствуют проверки успешности считывания и корректности данных).
int read_array(FILE *input, double **array, int *length) < double *arr; int arr_length, k; /* Считываем массив: сначала длину, потом элементы */ fscanf("%d", &arr_length); arr = (double *)malloc(arr_length * sizeof(double)); for(k = 0; k < arr_length; k++) fscanf("%lf", arr + k); /* Копируем результат по заданным адресам */ *length = arr_length; *array = arr; return 0; >
C++, можно ли узнать размер массива ?

а размер можно узнать, если ты позаботился о том что последний элемент NULL, если нет, то увы но никак.
ну а как в плюсах, точнее что есть в stl не знаю.
alphex_kaanoken ★★★
( 06.12.06 17:57:29 MSK )
Ответ на: комментарий от alphex_kaanoken 06.12.06 17:57:29 MSK
>размер можно узнать, если ты позаботился о том что последний элемент NULL, если нет, то увы но никак.
А в массиве в качестве значения NULL содержаться конечно не может.
К тому же это тогда обязательно должен быть массив указателей.
andron01
( 06.12.06 18:57:16 MSK )
Ответ на: комментарий от andron01 06.12.06 18:57:16 MSK

>А в массиве в качестве значения NULL содержаться конечно не может.
wtf? указатель это указатель. если у нас указатель на указатель то да нужно последним делать NULL. а в случае int* лучше держать например первым элементом количество элементов за ним замаллоченным, или отдельной переменной, не делать же лимитирующим значением 0 ?
к примеру если у меня по указателю находятся какие нить значение, например колебания того или иного, которые могут быть 0.
в случае с int[] уже выше показали как узнать.
alphex_kaanoken ★★★
( 06.12.06 19:15:01 MSK )
Ответ на: комментарий от aeuo 06.12.06 17:48:06 MSK
> можно если массива int arr[]
Нельзя. В списке аргументов int arr[] абсолютно равнозначно int *arr.
uj2 ★★★
( 06.12.06 20:09:13 MSK )
Ответ на: комментарий от uj2 06.12.06 20:09:13 MSK
> УКАЗАТЕЛЬ != МАССИВ!
int arr[5]; int *ar; ar = new int[5];
кстати где0то читал что в С массив == указатель .
anonymous
( 06.12.06 20:31:33 MSK )
Ответ на: комментарий от anonymous 06.12.06 20:31:33 MSK
> Забей на массивы (ибо зло) и пользуй std::vector. Там есть size().
anonymous
( 06.12.06 20:32:08 MSK )
Вот есть ещё такой немножко нестандартный подход. #include using std::cout; using std::endl; template void print(int (&arr)[Len]) < for (size_t i = 0; i < Len; ++i) cout int main() < int arr[] = ; print(arr); return 0; >
Legioner ★★★★★
( 06.12.06 21:21:23 MSK )
Ответ на: комментарий от Legioner 06.12.06 21:21:23 MSK
ага. и по одной функции для каждого размера =))
legk
( 06.12.06 22:30:30 MSK )
Ответ на: комментарий от legk 06.12.06 22:30:30 MSK
Зато компилятор может цикл развернуть, да и вообще заинлайнить всё 🙂
А так конечно vector надо пользовать.
Legioner ★★★★★
( 06.12.06 22:50:56 MSK )
Ответ на: комментарий от anonymous 06.12.06 20:31:33 MSK
> объясните разницу: > int arr[5]; int *ar; > ar = new int[5]; > кстати где0то читал что в С массив == указатель .
Не совсем. Имя массива это всегда указатель на ПЕРВЫЙ элемент. Например ты можешь сделать:
int *ma = malloc(5 * sizeof(int)); ma++;
shumer ★
( 07.12.06 13:05:16 MSK )
Ответ на: комментарий от anonymous 06.12.06 20:31:33 MSK
> объясните разницу: > int arr[5]; int *ar; > ar = new int[5]; > кстати где0то читал что в С массив == указатель . Не совсем. Имя массива это всегда указатель на ПЕРВЫЙ элемент. Например ты можешь сделать: int *ma = malloc(5 * sizeof(int)); ma++; Но нельзя: int a[] = ; a++;
shumer ★
( 07.12.06 13:06:19 MSK )
Ответ на: комментарий от shumer 07.12.06 13:06:19 MSK
> Имя массива это всегда указатель на ПЕРВЫЙ элемент.
Не всегда. Как раз в случаях операций ++ — sizeof x= . массив не генерирует указателя, а является немодифицируемым lvalue.
uj2 ★★★
( 07.12.06 19:50:54 MSK )
Ответ на: комментарий от uj2 07.12.06 19:50:54 MSK
Вобщем, как говорил Пендальф, нужно обратиться к первоисточнику:
A7.1. Генерация указателя
Если тип выражения или подвыражения есть «массив из T», где T — некоторый тип, то значением этого выражения является указатель на первый элемент массива, и тип такого выражения заменяется на тип «указатель на T». Такая замена не делается, если выражение является операндом унарного оператора &, или операндом операций ++, —, sizeof, или левым операндом присваивания, или операндом оператора . (точка). Аналогично, выражение типа «функция, возвращающая Т», кроме случая, когда оно является операндом для &, преобразуется в тип «указатель на функцию, возвращающую T».
shumer ★
( 07.12.06 21:15:01 MSK )
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.
Похожие темы
- Форум [C++] массивы и указатели (2010)
- Форум [C]Подскажите как компилер обязан передавать массивы в ф-ю (2008)
- Форум Многомерные массивы и указатели в ANSI C (2016)
- Форум Печать массива символов. (2014)
- Форум Сумма чисел двумерного массива во время компиляции (2018)
- Форум bash. массивы. не понятка с размером массива. (2012)
- Форум Ссылки на элементы массива в PHP (2012)
- Форум Задачка с массивом строк на Си (2008)
- Форум Странность с массивом нулевой длины в C++ (2016)
- Форум Изменение размера массива по указателю (2018)
size
sz = size( A ) возвращает вектор-строку, элементами которого являются длины соответствующих размерностей A . Например, если A матрица 3 на 4, затем size(A) возвращает векторный [3 4] .
Если A таблица или расписание, затем size(A) возвращает двухэлементный вектор-строку, состоящий из количества строк и количества табличных переменных.
szdim = size( A , dim ) возвращает длину размерности dim когда dim положительный целочисленный скаляр. Начиная в R2019b, можно также задать dim как вектор из положительных целых чисел, чтобы запросить несколько длин размерности за один раз. Например, size(A,[2 3]) возвращает длины вторых и третьих размерностей A в векторе 1 на 2 строки szdim .
szdim = size( A , dim1,dim2,…,dimN ) возвращает длины размерностей dim1,dim2,…,dimN в векторе-строке szdim (запускающийся в R2019b).
[ sz1. szN ] = size( ___ ) возвращает длины запрошенных размерностей A отдельно.
Примеры
Размер 4-D массива
Создайте случайный 4-D массив и возвратите его размер.
A = rand(2,3,4,5); sz = size(A)
sz = 1×4 2 3 4 5
Запросите только длину второго измерения A .
szdim2 = size(A,2)
szdim2 = 3
Начиная в R2019b, можно запросить несколько длин размерности за один раз путем определения векторного аргумента размерности. Например, найдите длины первых и третьих размерностей A .
szdim13 = size(A,[1 3])
szdim13 = 1×2 2 4
Найдите длины второго через четвертые размерности A .
szdim23 = size(A,2:4)
szdim23 = 1×3 3 4 5
В качестве альтернативы можно перечислить запрошенные размерности как отдельные входные параметры.
szdim23 = size(A,2,3,4);
Размер таблицы
Составьте таблицу с 5 строками и 4 переменными.
LastName = 'Smith';'Johnson';'Williams';'Jones';'Brown'>; Age = [38;43;38;40;49]; Height = [71;69;64;67;64]; Weight = [176;163;131;133;119]; BloodPressure = [124 93; 109 77; 125 83; 117 75; 122 80]; A = table(Age,Height,Weight,BloodPressure,'RowNames',LastName)
A=5×4 table Age Height Weight BloodPressure ___ ______ ______ _____________ Smith 38 71 176 124 93 Johnson 43 69 163 109 77 Williams 38 64 131 125 83 Jones 40 67 133 117 75 Brown 49 64 119 122 80
Найдите размер таблицы. Несмотря на то, что BloodPressure переменная содержит два столбца, size только считает количество переменных.
sz = size(A)
sz = 1×2 5 4
Длины размерности в качестве отдельных аргументов
Создайте случайную матрицу и возвратите количество строк и столбцов отдельно.
A = rand(4,3); [numRows,numCols] = size(A)
numRows = 4
numCols = 3
Входные параметры
A — Входной массив
скаляр | вектор | матрица | многомерный массив
Входной массив в виде скаляра, вектора, матрицы или многомерного массива.
Типы данных: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | logical | char | string | struct | function_handle | cell | categorical | datetime | duration | calendarDuration | table | timetable
Поддержка комплексного числа: Да
dim — Запрошенные размерности
положительный целочисленный скаляр | вектор из положительных целочисленных скаляров
Запрошенные размерности в виде положительного целочисленного скаляра или вектора из положительных целочисленных скаляров. Если элемент dim больше, чем ndims(A) , затем size возвращает 1 в соответствующем элементе выхода.
Типы данных: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
dim1,dim2,…,dimN — Список запрошенных размерностей
положительные целочисленные скаляры
Список запрошенных размерностей в виде положительных целочисленных скаляров, разделенных запятыми. Если элемент списка больше, чем ndims(A) , затем size возвращает 1 в соответствующем элементе выхода.
Типы данных: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Выходные аргументы
sz Размер массивов
вектор-строка из неотрицательных целых чисел
Размер массивов, возвращенный как вектор-строка из неотрицательных целых чисел.
- Каждый элемент sz представляет длину соответствующей размерности A . Если любой элемент sz равно 0 , затем A пустой массив.
- Если A скаляр, затем sz вектор-строка [1 1] .
- Если A таблица или расписание, затем sz двухэлементный вектор-строка, содержащий количество строк и количество переменных. Несколько столбцов в одной переменной не считаются.
- Если A вектор символов типа char , затем size возвращает вектор-строку [1 M] где M количество символов. Однако, если A строковый скаляр, size возвращает [1 1] потому что это — один элемент массива строк. Например, сравните выход size для вектора символов и строки:
szchar = size('mytext')
szchar = 1 6
szstr = size("mytext")
szstr = 1 1
Типы данных: double
szdim — Длины размерности
неотрицательный целочисленный скаляр | вектор из неотрицательных целочисленных скаляров
Длины размерности, возвращенные как неотрицательный целочисленный скаляр, когда dim скаляр и вектор-строка из неотрицательных целочисленных скаляров когда dim вектор. Если элемент аргумента заданного измерения больше, чем ndims(A) , затем size возвращает 1 в соответствующем элементе szdim .
Типы данных: double
sz1. szN — Длины размерности перечислены отдельно
неотрицательные целочисленные скаляры
Длины размерности, перечисленные отдельно, возвратились как неотрицательные целочисленные скаляры, разделенные запятыми.
- Когда dim не задан и меньше, чем ndims(A) выходные аргументы перечислены, затем все длины остального измерения сворачиваются в последний аргумент в списке. Например, если A трехмерный массив с размером [3 4 5] , затем [sz1,sz2] = size(A) возвращает sz1 = 3 и sz2 = 20 .
- Когда dim задан, количество выходных аргументов должно равняться количеству запрошенных размерностей.
- Если вы задаете больше, чем ndims(A) выходные аргументы, затем дополнительные запаздывающие аргументы возвращены как 1 .
Типы данных: double
Советы
- Чтобы определить, пуст ли массив, скаляр или матрица, использует функции isempty , isscalar , и ismatrix . Можно также определить ориентацию вектора с isrow и iscolumn функции.
Расширенные возможности
«Высокие» массивы
Осуществление вычислений с массивами, которые содержат больше строк, чем помещается в памяти.
Генерация кода C/C++
Генерация кода C и C++ с помощью MATLAB® Coder™.
Генерация кода графического процессора
Сгенерируйте код CUDA® для NVIDIA® графические процессоры с помощью GPU Coder™.
Генерация HDL-кода
Сгенерируйте Verilog и код VHDL для FPGA и проекты ASIC с помощью HDL Coder™.
Основанная на потоке среда
Запустите код в фоновом режиме с помощью MATLAB® backgroundPool или ускорьте код с Parallel Computing Toolbox™ ThreadPool .
Эта функция полностью поддерживает основанные на потоке среды. Для получения дополнительной информации смотрите функции MATLAB Запуска в Основанной на потоке Среде.
Массивы графического процессора
Ускорьте код путем работы графического процессора (GPU) с помощью Parallel Computing Toolbox™.
Эта функция полностью поддерживает массивы графического процессора. Для получения дополнительной информации смотрите функции MATLAB Запуска на графическом процессоре (Parallel Computing Toolbox) .
Распределенные массивы
Большие массивы раздела через объединенную память о вашем кластере с помощью Parallel Computing Toolbox™.
Эта функция полностью поддерживает распределенные массивы. Для получения дополнительной информации смотрите функции MATLAB Запуска с Распределенными Массивами (Parallel Computing Toolbox) .
Смотрите также
Представлено до R2006a
Открытый пример
У вас есть модифицированная версия этого примера. Вы хотите открыть этот пример со своими редактированиями?
Документация MATLAB
Поддержка
- MATLAB Answers
- Помощь в установке
- Отчеты об ошибках
- Требования к продукту
- Загрузка программного обеспечения
© 1994-2021 The MathWorks, Inc.
- Условия использования
- Патенты
- Торговые марки
- Список благодарностей
Для просмотра документации необходимо авторизоваться на сайте
Войти
Памятка переводчика
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста — например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.
Как узнать размер массива переданного в функцию?
но в SIZE сохраняется 1, независимо от размера массива. Можно, конечно, вместе с массивом передать в функцию и его размер, но может существует более изящное решение? P.S.: Кстати, заметил нечто странное. Запускал эту программу через Visual Studio и Qt. В VS в SIZE сохраняется 1, а в Qt 2.
Отслеживать
44.8k 3 3 золотых знака 38 38 серебряных знаков 89 89 бронзовых знаков
задан 14 окт 2016 в 13:34
130 1 1 золотой знак 1 1 серебряный знак 8 8 бронзовых знаков
sizeof(Array) — размер указателя на int в данном случае.
14 окт 2016 в 13:37
При имеющейся сигнатуре размер массива Вы узнать не сможете.
14 окт 2016 в 13:38
А при чём тут C++? Размер массива в C++ узнать очень просто: методом size() (если это, скажем, vector ) или аналогичным.
14 окт 2016 в 13:40
@PinkTux так вопрос про обычные массивы, не STL-контейнеры же. Хотя согласен, в С++ по возможности стоит отказываться от сишных массивов в пользу vector, array и прочего.
14 окт 2016 в 13:42
Вот еще может помочь
14 окт 2016 в 13:42
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
У вас параметр функции foo объявлен как указатель типа int *
void foo(int* Array); ^^^^^^^^^^
Следовательно внутри функции выражение
sizeof(Array)/sizeof(int)
sizeof(int *)/sizeof(int)
Если, например, размер указателя, то есть типа int * , равен 8 байтам, а размер типа int равен 4 байтам, то в итоге вы получите 2. Если же при этом размер типа int равен также 8 байтам (64-битовая ОС), то вы получите в итоге 1.
Но даже если вы объявите эту функцию как
void foo(int Array[]);
void foo(int Array[10]);
все равно параметр функции неявно преобразуется в указатель на элемент массива. То есть эти два объявления функции объявляют одну и ту же функцию и эквивалетны следующему объявлению
void foo(int* Array);
Так что внутри функции вы снова будете иметь дело с указателем.
Когда массив передается по значению, то вам следует также объявлять второй параметр, который задает размер массива.
Или массив должен иметь некоторый граничный элемент с уникальным значением, по которому можно определить число актуальных элементов, как это имеет место, например, со строками, когда строки завершаются нулем, то есть символом ‘\0’ .
То есть в общем случае вам следует объявлять функцию как
void foo(int* Array, size_t n);
где n — это размер массива.
Другой подход — это объявлять параметр как ссылку на массив. В этом случае длина массива будет известна внутри функции. Например
void foo( int ( &Array )[10] ) < const size_t = sizeof( Array)/ sizeof( *Array ); >
Недостаток этого объявления состоит в том, что эта функция может иметь дело только с массивами, заданного в ее параметре размера.
Чтобы обойти это ограничение, вы можете объявить шаблонную функцию. Например,
template void foo( int ( &Array )[N] )
В этом случае компилятор, используя шаблон, создаст столько функций, сколько массивов разной длины были использованы в качестве аргумента.