Задать вопрос
@AslHack

Имя массива это адрес первого элемента или указатель на его первый элемент в Си?

Есть код:

int arrOne[5] = {1,2,3,4,5};

Тут arrOne это адрес его первого элемента? Или указатель на его первый элемент? Или в указатель он превращается только когда это нужно (к примеру в арифметике адресов)? Или оба варианта верны?

Немного другая тема:

int arrTwo[3][2] = {{1,2}, {3,4}, {5,6}};

А с двумерным массивом как? Тут arrTwo это адрес первого элемента или указатель на его первый элемент т.е {1,2}? И получается arrTwo это адрес самого первого элемента {1,2} или же адрес первого элемента первого подмассива т.е {1}?
  • Вопрос задан
  • 460 просмотров
Подписаться 2 Средний 1 комментарий
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    Разработчик C++
    9 месяцев
    Далее
  • Skillbox
    Разработчик на C++
    7 месяцев
    Далее
  • Нетология
    Разработчик на C++: Профессия + специализация + нейросети
    12 месяцев
    Далее
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
arrOne и arrTwo - это переменные, типов int[5] и int[3][2]. Это на уровне C. Под капотом там указатели: компилятор знает адрес начала массива. Путаницу может вызвать то, что массивы в языке C тождественны указателям на начало с той лишь разницей, что компилятор знает его длину и всякие sizeof() сработают правильно.
Соответственно, arrOne неявно приводится к int*, а arrTwo к int (*)[2] (указатель на массив из 2 элементов, что в свою очередь неявно приводиться к указателю на указатель на инт).

Поэтому работает код:
int a[3][2];
   int (*b)[2];
   b = a;


Можно считать, что arrOne - указатель на первый элемент int, а arrTwo - указатель на первую строку int[2], по совместительству на первый элемент в первой строке:
int x = *arrOne;
   int y = **arrTwo; // с одной * не сработает ибо int[2], оно же int* к int не приводиться.
   int *z = arrOne+2; // указатель на 3-ий элемент
   int *w = arrTwo + 1; // указатель на вторую строку (первый элемент в ней).


Но лучше на закапываться в адрессную арифметику, а воспринимать массивы, как свой отдельный тип данных. Не пишите arrOne+1, а пишите arrOne[1] и не парьтесь.

Даже для int переменных компилятор знает их адрес, так что там под капотом тоже есть указатель. Не очень большая разница.

Массив - это индексируемая область памяти. Единственное, о чем надо помнить, что массивы всегда передаются по ссылке. Их дешево передавать в функции и изменения массива внутри всегда видны снаружи.
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
GavriKos
@GavriKos
Микропетпроджект - домашнее облако homeCloud
А чем по вашему адрес от указателя отличается?

Про размерности массив ответ простой - arrTwo - это начало массива, первый элемент, его адрес в памяти. А дальше работает адресная арифметика.
Ответ написан
@Griglapidus
C++/Qt
C Array в памяти выделяется одним сплошным массивом не зависимо от размерности. его при желании даже можно преобразовать в 1 мерный массив:
int arr2[3][2] = {{1,2},{3,4},{5,6}};
auto arr1 = reinterpret_cast<int(&)[6]>(arr2);
Ответ написан
Комментировать
Adamos
@Adamos
Имя массива - это строка в коде программы, по которой компилятор определяет, что работает с вот этой конкретной областью памяти. Зная ее начальный адрес и применяя адресную арифметику для нахождения адреса хоть линейного, хоть двумерного элемента (там просто arr[x][y] превращается в начальный адрес + (x * второй размер массива + y) * размер переменной. Массивы в С - это всегда плоская область памяти, размерность существует только для программиста, для удобства).
Указатель - это и есть переменная, в которой хранится адрес другой переменной. Например, первого элемента массива. Объявление указателя вместо целого числа просто позволяет компилятору понять, что программист именно это и имел в виду, и не ругаться на подозрительные операции.
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Если ты работаешь с С++ то тебе объективно лучше использовать векторы из std.
У них - больше смысловых возможностей и они безопаснее с точки зреня контроля над ресурсами.

Многомерный массив
int arrTwo[3][2] = {{1,2}, {3,4}, {5,6}};
в обоих языках эмулируется через массив массивов.

Но его имеет смысл использовать когда у тебя есть матрица где число элементов в строке "скачет".
Например так
{{2,3,5}, {,7,11}, {13}};
В этом случае использование такого зубчатого массива оправдано. Мы экономим ресурсы.
Это может быть полезно для микро-контроллеров например где память меряется килобайтами.

Если матрица - прямоугольная то ее можно просто "отобразить" на плоский массив.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы