Int arr c что это
Перейти к содержимому

Int arr c что это

  • автор:

C++ -что означает запись: int *arr, N, min, max;

Int — целочисленный тип, диапазон принимаюших значений От -2 147 483 648 до 2 147 483 647
Arr — массив, который объявлен в начале программы
N — переход на другую строку
Min — минимальное значение числа
Max — максимальное значение числа

Переменные N, min, max — типа int (целые). Переменная arr — указатель на int. А VaJITeR нафантазировал, как они могут использоваться. Да, могут и так. А могут и не так.

What does *arr[] mean? [closed]

Want to improve this question? Add details and clarify the problem by editing this post.

Closed 6 years ago .

i have this code from my previous exam and it’s the first time I see this *arr[] . What does that mean? Is it a matrix or an array? And what does it contain?

Nisse Engström's user avatar

3 Answers 3

As standalone expression *arr[] is not valid.

For variable definitions there are two meanings here, depending of the context in which such an expression appears:

Variable definition with initialiser (as per the OP’s snippet)

This defines an array of pointer to int , with its number of elements being determined by the number of elements in its initialiser. In the above example arr will have three elements.

Variable definition inside a function’s parameter list

If used like like this, that is inside a function declaration/definition

it in fact defines an int ** , a pointer to pointer to int . In the context of a function declaration/definition int * arr[] and int ** arr are equivalent, or more general T*[] equals T** .

To explicitly state this: In no case int * arr[] defines any int s.

Индексаторы

Программисты хорошо знакомы с процессом доступа к индивидуальным элементам, содержащимся в стандартных массивах, через операцию индекса ([]). В C# имеется возможность проектировать специальные классы и структуры, которые могут быть индексированы подобно стандартному массиву, посредством определения . Это конкретное языковое средство наиболее полезно при создании специальных типов коллекций (обобщенных и необобщенных). Индексаторы могут быть одно- или многомерными.

Одномерные индексаторы

Ниже приведена общая форма одномерного индексатора:

где тип_элемента обозначает конкретный тип элемента индексатора. Следовательно, у каждого элемента, доступного с помощью индексатора, должен быть определенный тип_элемента. Этот тип соответствует типу элемента массива. Параметр индекс получает конкретный индекс элемента, к которому осуществляется доступ. Формально этот параметр совсем не обязательно должен иметь тип int, но поскольку индексаторы, как правило, применяются для индексирования массивов, то чаще всего используется целочисленный тип данного параметра.

В теле индексатора определены два аксессора (т.е. средства доступа к данным): get и set. Аксессор подобен методу, за исключением того, что в нем не объявляется тип возвращаемого значения или параметры. Аксессоры вызываются автоматически при использовании индексатора, и оба получают индекс в качестве параметра. Так, если индексатор указывается в левой части оператора присваивания, то вызывается аксессор set и устанавливается элемент, на который указывает параметр индекс. В противном случае вызывается аксессор get и возвращается значение, соответствующее параметру индекс. Кроме того, аксессор set получает неявный параметр value, содержащий значение, присваиваемое по указанному индексу.

Давайте рассмотрим пример:

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

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

На применение индексаторов накладываются два существенных ограничения. Во-первых, значение, выдаваемое индексатором, нельзя передавать методу в качестве параметра ref или out, поскольку в индексаторе не определено место в памяти для его хранения. И во-вторых, индексатор должен быть членом своего класса и поэтому не может быть объявлен как static.

C Language
Массивы

Массивы представляют собой производные типы данных, представляющие упорядоченный набор значений («элементов») другого типа. Большинство массивов в C имеют фиксированное количество элементов любого одного типа, и его представление хранит элементы смежно в памяти без пробелов или отступов. C допускает многомерные массивы, элементами которых являются другие массивы, а также массивы указателей.

C поддерживает динамически распределенные массивы, размер которых определяется во время выполнения. C99 и более поздние версии поддерживают массивы переменной длины или VLA.

Синтаксис

  • имя типа [длина]; / * Определить массив «type» с именем «name» и длиной «length». * /
  • int arr [10] = <0>; / * Определить массив и инициализировать ВСЕ элементы в 0. * /
  • int arr [10] = <42>; / * Определить массив и инициализировать 1-й элемент до 42, а остаток — 0. * /
  • int arr [] = <4, 2, 3, 1>; / * Определить и инициализировать массив длиной 4. * /
  • arr [n] = значение; / * Установленное значение при индексе n. * /
  • значение = arr [n]; / * Получить значение по индексу n. * /

замечания

Зачем нам нужны массивы?

Массивы обеспечивают способ организации объектов в совокупность с его собственным значением. Например, строки C представляют собой массивы символов ( char s) и строку, такую ​​как «Hello, World!». имеет значение как совокупность, которая не присуща персонажам индивидуально. Аналогично, массивы обычно используются для представления математических векторов и матриц, а также списков многих видов. Более того, без какого-либо элемента для группировки элементов нужно будет решать каждый отдельно, например, через отдельные переменные. Мало того, что это громоздко, он не легко вмещает коллекции разной длины.

Массивы неявно преобразуются в указатели в большинстве контекстов .

За исключением случаев, когда он является операндом оператора sizeof оператором _Alignof (C2011) или оператором unary & (address-of) или как строковый литерал, используемый для инициализации (другого) массива, массив неявно преобразуется в ( «decays to») указатель на свой первый элемент. Это неявное преобразование тесно связано с определением оператора субтипирования массива ( [] ): выражение arr[idx] определяется как эквивалентное *(arr + idx) . Кроме того, поскольку арифметика указателя коммутативна, *(arr + idx) также эквивалентна *(idx + arr) , что, в свою очередь, эквивалентно idx[arr] . Все эти выражения действительны и оцениваются с одинаковым значением при условии, что либо idx либо arr является указателем (или массивом, который распадается на указатель), а другой является целым числом, а целое число является допустимым индексом в массив на который указывает указатель.

В качестве частного случая заметим, что &(arr[0]) эквивалентно &*(arr + 0) , что упрощается до arr . Все эти выражения взаимозаменяемы везде, где последний разпад указателя. Это просто снова выражает, что массив распадается на указатель на его первый элемент.

Напротив, если адрес-оператор применяется к массиву типа T[N] ( т.е. &arr ), тогда результат имеет тип T (*)[N] и указывает на весь массив. Это отличается от указателя на первый элемент массива, по крайней мере, относительно арифметики указателя, которая определяется в терминах размера заостренного типа.

Функциональные параметры не являются массивами .

Хотя первое объявление foo использует синтаксис типа массива для параметра a , такой синтаксис используется для объявления параметра функции, объявляющего этот параметр как указатель на тип элемента массива. Таким образом, вторая сигнатура для foo() семантически идентична первой. Это соответствует распаду значений массива указателям, где они отображаются в качестве аргументов для вызова функции, так что если переменная и параметр функции объявлены с тем же типом массива, то значение этой переменной подходит для использования в вызове функции как аргумент, связанный с параметром.

Объявление и инициализация массива

Общий синтаксис объявления одномерного массива

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

Объявление массива (массив из 10 переменных int в этом случае) выполняется следующим образом:

теперь он имеет неопределенные значения. Чтобы гарантировать, что при объявлении он имеет нулевые значения, вы можете сделать это:

В массивах также могут быть инициализаторы, в этом примере объявляется массив из 10 int , где первые 3 int будут содержать значения 1 , 2 , 3 , все остальные значения будут равны нулю:

В приведенном выше методе инициализации первое значение в списке будет присвоено первому члену массива, второе значение будет присвоено второму элементу массива и так далее. Если размер списка меньше размера массива, то, как и в предыдущем примере, остальные члены массива будут инициализированы нулями. С назначенной инициализацией списка (ISO C99) возможна явная инициализация элементов массива. Например,

В большинстве случаев компилятор может вывести длину массива для вас, этого можно добиться, оставив квадратные скобки пустыми:

Объявление массива нулевой длины недопустимо.

В C99 были добавлены массивы переменной длины (VLA для краткости) и были добавлены в C11. Они равны нормальным массивам, с одной, важной, разницей: длина не обязательно должна быть известна во время компиляции. У VLA есть время автоматического хранения. Только указатели на VLA могут иметь статическую продолжительность хранения.

Важный:

VLA потенциально опасны. Если для массива vla в приведенном выше примере требуется больше места в стеке, чем доступно, стек будет переполняться. Поэтому использование VLA часто не поощряется в руководствах по стилю, а также книгами и упражнениями.

Очистка содержимого массива (обнуление)

Иногда необходимо установить массив в ноль после завершения инициализации.

Общим сокращением к вышеуказанному циклу является использование memset() из <string.h> . Проходящий array как показано ниже, заставляет его распадаться на указатель на его 1-й элемент.

Как и в этом примере, array представляет собой массив, а не только указатель на 1-й элемент массива (см. Длину массива на том, почему это важно), возможно третий вариант для вывода из массива:

Длина массива

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

Однако в большинстве контекстов, где массив появляется в выражении, он автоматически преобразуется в указатель («decays to») на свой первый элемент. Случай, когда массив является операндом оператора sizeof является одним из небольшого числа исключений. Результирующий указатель сам по себе не является массивом, и он не несет никакой информации о длине массива, из которого он был получен. Поэтому, если эта длина необходима в сочетании с указателем, например, когда указатель передается функции, он должен передаваться отдельно.

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

Функция может быть реализована следующим образом:

Обратите внимание, в частности, что хотя объявление input параметра похоже на объявление массива, оно фактически объявляет input как указатель (для int ). Это точно эквивалентно объявлению input как int *input . То же самое было бы верно, даже если бы было дано измерение. Это возможно, потому что массивы никогда не могут быть фактическими аргументами для функций (они распадаются на указатели, когда они появляются в выражениях вызова функций), и их можно рассматривать как мнемонические.

Это очень распространенная ошибка, чтобы попытаться определить размер массива из указателя, который не может работать. НЕ ДЕЛАЙТЕ ЭТОГО:

На самом деле эта конкретная ошибка настолько распространена, что некоторые компиляторы ее распознают и предупреждают об этом. clang , например, выдает следующее предупреждение:

Установка значений в массивах

Доступ к значениям массива обычно выполняется с помощью квадратных скобок:

В качестве побочного эффекта операндов к оператору + заменить (-> коммутативный закон) следующее эквивалентно:

так что следующие утверждения эквивалентны:

C не выполняет никаких пограничных проверок, доступ к содержимому вне объявленного массива не определен (доступ к памяти за пределами выделенного фрагмента ):

Определить массив и элемент массива доступа

Выделить и нуль инициализировать массив с заданным пользователем размером

Эта программа пытается сканировать в значении без знака со стандартного ввода, выделяет блок памяти для массива из n элементов типа int , вызывая функцию calloc() . Память инициализируется всеми нулями последней.

В случае успеха память освобождается вызовом free() .

Итерация через массив эффективно и порядок строк

Массивы в C можно рассматривать как непрерывный кусок памяти. Точнее, последнее измерение массива — это смежная часть. Мы называем это строковым порядком . Понимая это и тот факт, что ошибка кэша загружает полную кеш-строку в кеш при доступе к нераскрытым данным, чтобы предотвратить последующие ошибки кэша, мы видим, почему доступ к массиву размера 10000×10000 с array[0][0] потенциально может быть загружен в array[0][1] в кеше, но доступ к array[1][0] сразу же сгенерировал бы вторую ошибку кэша, так как это sizeof(type)*10000 bytes from array[0][0] , и, следовательно, в той же строке кэша. Вот почему итерация таким образом неэффективна:

Итерация таким образом более эффективна:

В том же духе, поэтому при работе с массивом с одним измерением и несколькими индексами (скажем, 2 измерения здесь для простоты с индексами i и j) важно выполнить итерацию по массиву следующим образом:

Или с 3 измерениями и индексами i, j и k:

Или более общим образом, когда у нас есть массив с элементами N1 x N2 x . x Nd , d измерениями и индексами, отмеченными как n1, n2, . nd, смещение рассчитывается так

формула

Многомерные массивы

Язык программирования C позволяет использовать многомерные массивы . Вот общая форма объявления многомерного массива —

Например, следующее объявление создает трехмерный (5 x 10 x 4) целочисленный массив:

Двумерные массивы

Простейшей формой многомерного массива является двумерный массив. Двумерный массив представляет собой, по существу, список одномерных массивов. Чтобы объявить двумерный целочисленный массив размеров mxn, мы можем написать следующее:

Где type может быть любым допустимым типом данных C ( int , float и т. Д.), А arrayName может быть любым допустимым идентификатором C. Двумерный массив можно визуализировать как таблицу с m строками и n столбцами. Примечание : порядок имеет значение в C. Массив int a[4][3] не совпадает с массивом int a[3][4] . Количество строк приходит сначала в качестве С является строка -Майора языка.

Двумерный массив a , содержащий три строки и четыре столбца, можно показать следующим образом:

визуальная компоновка 2D-массива в виде таблицы

Таким образом, каждый элемент в массиве a идентифицируется именем элемента формы a[i][j] , где a — это имя массива, i представляет, какую строку и j представляет собой какой столбец. Напомним, что строки и столбцы нулевые индексируются. Это очень похоже на математическое обозначение для подписи двухмерных матриц.

Инициализация двумерных массивов

Многомерные массивы могут быть инициализированы путем задания скобок для каждой строки. Следующие определяют массив с 3 строками, где каждая строка имеет 4 столбца.

Вложенные фигурные скобки, которые указывают предполагаемую строку, являются необязательными. Следующая инициализация эквивалентна предыдущему примеру:

Хотя метод создания массивов с вложенными фигурными скобками является необязательным, он настоятельно рекомендуется, поскольку он более читабельным и понятным.

Доступ к двумерным элементам массива

Доступ к элементу в двумерном массиве осуществляется с помощью индексов, то есть индекса строки и индекса столбца массива. Например,

Вышеприведенный оператор берет 4-й элемент из 3-й строки массива. Давайте проверим следующую программу, в которой мы использовали вложенный цикл для обработки двумерного массива:

Когда приведенный выше код компилируется и выполняется, он производит следующий результат:

Трехмерный массив:

3D-массив по существу представляет собой массив массивов массивов: это массив или набор 2D-массивов, а 2D-массив — массив из 1-го массива.

визуальная компоновка 2D-массива в виде набора таблиц

Карта памяти 3D-массива:

3D-массив, встроенный в память

Инициализация 3D-массива:

Мы можем иметь массивы с любым количеством измерений, хотя вполне вероятно, что большинство создаваемых массивов будут иметь один или два измерения.

Итерация через массив с помощью указателей

Здесь, при инициализации p в первом for цикла условиях, массив a распадается на указатель на его первый элемент, как и во всех местах, где используется такая переменная массива.

Затем ++p выполняет арифметику указателя на указателе p и идет один за другим через элементы массива и ссылается на них путем разыменования их с помощью *p .

Передача многомерных массивов в функцию

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *