Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.93/56: Рейтинг темы: голосов - 56, средняя оценка - 4.93
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24

Имя массива в С++ это указатель или ссылка?

12.06.2020, 14:18. Показов 12605. Ответов 133
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пытаюсь понять что такое имя массива в С++! Указатель или ссылка? Сразу скажу что пока рассматриваю только статические массивы.
Теория говорит что это указатель, собственно поэтому для имени массива применима арифметика указателей.
Но! раз это указатель, то значит это переменная под которую компилятор выделил ячейку памяти в которой должен храниться адрес первого элемента массива arr[0]. Раз такая ячейка памяти есть то по идее можно узнать ее адрес так - &arr!
К сожалению такой трюк не работает и получается что &arr==arr! Для меня это никак не укладывается под описание указателя.

Попробовал выяснить по аналогии с простой переменной что такое указатель, а что такое ссылка!
Вот простенький код для простой переменной и результат его выполнения:
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        int a = 10;
    int* b = &a;
    int** c = &b;
    cout << "Указатели" << endl;
    cout << "ТИП" << "\t\t" << "int" << "\t" << "int*" << "\t\t" << "int*" << "\t\t" << "int" << "\t" << "int**" << "\t\t" << "int**" << "\t\t" << "int*" << "\t\t" << "int" << endl;
    cout << "ОПЕРАЦИЯ" << "\t" << "a" << "\t" << "&a" << "\t\t" << "b = &a" << "\t\t" << "*b" << "\t" << "&b" << "\t\t" << "c = &b" << "\t\t" << "*c" << "\t\t" << "**c" << endl;
    cout << "Значение" << "\t" << a << "\t" << &a << "\t" << b << "\t" << *b << "\t" << &b << "\t" << c << "\t" << *c << "\t" << **c << endl << endl;
 
    cout << "Ссылки" << endl;
    int& d = a;
    int* e = &d;
    cout << "ТИП" << "\t\t" << "int&" << "\t" << "\t" << "\t" << "int*" << "\t\t" << "int" << "\t" << "int*" << endl;
    cout << "ОПЕРАЦИЯ" << "\t" << "d" << "\t" << "&d" << "\t\t" << "e = &d" << "\t\t" << "*e" << "\t" << "&e" << endl;
    cout << "Значение" << "\t" << d << "\t" << &d << "\t" << e << "\t" << *e << "\t" << &e << endl;


Результат говорит о том что если переменная "b" - указатель на переменную "a", то переменная b находится в памяти по адресу &b и содержит значение адреса переменной a равное &a. Все вполне согласуется с теорией.
Если же переменная "d" - ссылка на переменную "a", то для переменной b вроде как не выделяется памяти, по крайней мере собственного адреса в памяти для переменной d нет и операция &d дает лишь адрес переменной a.

Если поступить аналогично с массивом?
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
        const int size = 10;
    int arr[size] = {0,1,2,3,4,5,6,7,8,9};
    int* pArr = arr;
 
    void* a = &arr;         // студия ругается на cout << *a
    void** c = &a;          // студия ругается на cout << **с
    void* d = &a;           // студия ругается на cout << *d
 
    void* b = &pArr;
    void** e = &b;
    void* f = &b;
 
    cout << "arr + i" << "\t\t" << "arr[i]" << "\t" << "*(arr + i)" << "\t" << "&arr" << "\t\t" << "a = &arr" << "\t" << "&a" << "\t\t" << "c = &a" << "\t\t" << "d = &a" << "\t\t" << "*c" << endl;
    
    for (int i = 0; i < 10; i++)
    {
    cout << arr + i << "\t" << arr[i] << "\t" << *(arr + i) << "\t\t" << &arr << "\t" << a << "\t" << &a << "\t" << c << "\t" << d << "\t" << *c << endl;
    }
    
    cout << "pArr + i" << "\t" << "pArr[i]" << "\t" << "*(pArr + i)" << "\t" << "&pArr" << "\t\t" << "b = &pArr" << "\t" << "&b" << "\t\t" << "e = &b" << "\t\t" << "f = &b" << "\t\t" << "*e" << endl;
 
    for (int i = 0; i < 10; i++)
    {
    cout << pArr + i << "\t" << pArr[i] << "\t" << *(pArr + i) << "\t\t" << &pArr << "\t" << b << "\t" << &b << "\t" << e << "\t" << f << "\t" << *e << endl;
    }


Если объявить указатель pArr на массив arr, то видно что для pArr аналогично указателю простой переменной выделяется место в памяти с адресом &pArr в которой содержится адрес первого элемента массива arr[0]. Все как бы укладывается в мои представления.
А что же с именем массива? Ведь утверждается что это указатель на 1й элемент этого массива arr[0].
Операция &arr дает адресс такой же как и у первого элемента массива, как будто нет никакого указателя а есть ссылка по аналогии с обычной переменной!
Но почему же тогда для имени массива доступна арифметика указателя? для обычной ссылки такого ведь нет.
В последнем примере все указатели имеют тип void* (не знаю насколько это корректно), поэтому думаю что корректней следующий код, но результат тот же самый! Имя массива как будто является ссылкой а не указателем.
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const int size = 10;
    int arr[size] = {0,1,2,3,4,5,6,7,8,9};
 
    int* pArr = arr;
 
    int(*a)[size] = &arr;
    int(**c)[size] = &a;
    
    int** b = &pArr;
    int*** e = &b;
    
    cout << "arr + i" << "\t\t" << "arr[i]" << "\t" << "*(arr + i)" << "\t" << "a = &arr" << "\t" << "*a" << "\t\t" << "c = &a" << "\t\t" << "*c" << "\t\t" << "**c" << endl;
    
    for (int i = 0; i < 10; i++)
    {
    cout << arr + i << "\t" << arr[i] << "\t" << *(arr + i) << "\t\t" << a << "\t" << *a << "\t" << c << "\t" << *c << "\t" << **c << endl;
    }
    
    cout << endl;
    cout << "pArr + i" << "\t" << "pArr[i]" << "\t" << "*(pArr + i)" << "\t" << "b = &pArr" << "\t" << "*b" << "\t\t" << "**b" << "\t\t" << "e = &b" << "\t\t" << "*e" << endl;
 
    for (int i = 0; i < 10; i++)
    {
        cout << pArr + i << "\t" << pArr[i] << "\t" << *(pArr + i) << "\t\t" << b << "\t" << *b << "\t" << **b << "\t\t" << e << "\t" << *e << "\t" << endl;
    }



У меня такое представление об указателях, что это переменная которая в памяти имеет собственное место т.е. имеет свой адрес и содержит адрес переменной на которую указывает. примерно как на следующем рисунке:


Все же объясните что такое имя массива? указатель или ссылка? или у меня неправильное представление об этих вещах?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
12.06.2020, 14:18
Ответы с готовыми решениями:

Указатель или ссылка на указатель. В чем разница?
Есть вопрос про указатели и ссылки на указатели :scratch: Хочу в функциях f1() и в f2() динамически выделить память и возвратить этот...

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

Ссылка на объект в памяти и указатель это одно и тоже?
Разобрался со смыслом различий значимых типов и ссылочных типов, а так же с особенностями их передачи через ref и out. Но не понятно...

133
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 23:53
Студворк — интернет-сервис помощи студентам
argcargv,
1) хорошо, что про std::move не вспомнил

2) я к тому, что будет в returns ты это не уточнил

3) да никто не спорит с тем что идея назначить указателям значения из твоей ссылки было позже чем addressof

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

5) можно и так ) не суть, главное что бы отражало ту картину которую ты нарисовал

ладно, я вижу разговор к сожалению заходит в тупик, в связи с чем предлагаю замять это дело...
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
12.06.2020, 23:58
Цитата Сообщение от Undisputed Посмотреть сообщение
я к тому, что будет в returns ты это не уточнил
???
Цитата Сообщение от argcargv Посмотреть сообщение
Нужно банально написать "pointer to" вместо "address of".
Можно даже вместо "The actual address of".
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
13.06.2020, 00:17
argcargv,
Круто... А ты дальше читал?
A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory])
Ничего, что значения из списка представляют собой адреса?
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
13.06.2020, 00:21
Цитата Сообщение от Undisputed Посмотреть сообщение
Круто... А ты дальше читал?
Читал.
Цитата Сообщение от Undisputed Посмотреть сообщение
Ничего, что значения из списка представляют собой адреса?
Ничего, а что?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
13.06.2020, 01:05
argcargv,

А то что тут Имя массива в С++ это указатель или ссылка?
Ты говоришь что оператор определён для значений указателя а не для адресов.
Затем тебя никак не смущает что значение указателя вполне себе может быть адресом.
Т.к значение может быть адресом, и сравниваем мы значения, в получается что в таком случае мы сравниваем адреса.

Тогда я так понимаю твой вариант описания addressof ошибочный... значение указателя в твоей интерпретации по ссылке выше не бывает адресом, оказывается противоречивым. Потому что если значение указателя не бывает адресом, то как тогда addressof может возвращать предлагаемый тобой pointer? Ведь значение поинтера как мы выяснили может быть адресом )

Добавлено через 3 минуты
обновил
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
13.06.2020, 01:18
Цитата Сообщение от Undisputed Посмотреть сообщение
значение указателя вполне себе может быть адресом.
Не может.
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
13.06.2020, 01:58
Пока до мордобоя не дошло:

Кликните здесь для просмотра всего текста
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
13.06.2020, 03:51
Цитата Сообщение от cahmep Посмотреть сообщение
но вроде же передача значений в функцию и обратно через стек происходит... а стэк это участок памяти... работа со стеком идет через регистры, т.е. в какой-то момент наверное как раз там где "return a" участвуют и стек и регистры.
Это чудовищно неверный способ понимать язык С++.
Хорошо бы вы еще раз рассмотрели пример выше и поняли, что совсем необязательно привлекать какой-то стек и регистры для представления того, что там происходит. Стек и регистры возникают, если вообще возникают, значительно позже. И когда они возникли, то язык С++ уже закончился.

Цитата Сообщение от cahmep Посмотреть сообщение
указатель, как оказалось, это не обязательно переменная в памяти.
Зря вы выделяете здесь конкретно указатели. Это в общем-то относится к любым типам в определенных контекстах.
0
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
13.06.2020, 06:52  [ТС]
Цитата Сообщение от argcargv Посмотреть сообщение
Не может.
Аааааа!!! Взрыв мозга!!!
В моей голове итак сейчас такая каша! ... а тут еще это!
Каким образом значение указателя не может быть адресом?
Как по мне так оно не может быть ничем другим кроме адреса! Хоть он явный хоть он неявный - это должно быть какое-то число равное адресу.
Собственно потому его так и назвали наверное что он указывает и говорит о том что какой-то объект находится по конкретному адресу содержащемуся в указателе.
Что-то слишком дохрена абстракций на мою голову... это меня убивает)
Чем мне нравится ассемблер - так это своей конкретикой... есть память, есть регистры... и делай с ними все что хочешь в рамках набора команд! Все просто и конкретно.

Добавлено через 3 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
Это чудовищно неверный способ понимать язык С++.
Хорошо бы вы еще раз рассмотрели пример выше и поняли, что совсем необязательно привлекать какой-то стек и регистры для представления того, что там происходит. Стек и регистры возникают, если вообще возникают, значительно позже. И когда они возникли, то язык С++ уже закончился.
Скорей всего так и есть! Я только начал разбираться с языком, и пока пытаюсь переложить свои знания из ассемблера применительно к нему, найти какую-то аналогию.
0
13.06.2020, 06:53

Не по теме:

Цитата Сообщение от cahmep Посмотреть сообщение
Аааааа!!! Взрыв мозга!!!
да он тролль.

0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12943 / 6810 / 1821
Регистрация: 18.10.2014
Сообщений: 17,235
13.06.2020, 06:54
Цитата Сообщение от cahmep Посмотреть сообщение
Чем мне нравится ассемблер - так это своей конкретикой... есть память, есть регистры... и делай с ними все что хочешь в рамках набора команд! Все просто и конкретно.
Разница между семантиками команд lea регистр, адрес и mov регистр, указатель (в терминах ассемблера x86) - это фактически та же разница между lvalue и указателем, которую мы обсуждаем здесь. И в ассемблере тоже они зачастую вызывают трудности с пониманием.
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
13.06.2020, 09:52
Цитата Сообщение от cahmep Посмотреть сообщение
Каким образом значение указателя не может быть адресом?
Какими значения указателей определили в стандарте, такими они и будут. Сейчас определено так, что такого значения как "адрес" среди возможных [видов] значений указателей нет.

Понятие "адрес" связано со значениями указателей косвенно и особо в языке нигде не участвует. Из мест, где играет роль то, какой адрес представляют значения указателей, могу вспомнить только: сравнение указателей на равенство и std::launder.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
13.06.2020, 10:30
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
lea регистр, адрес и mov регистр, указатель
offset в источнике команды mov не пропустил? и что понимается под адрес и указатель?
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
14.06.2020, 08:41
Цитата Сообщение от cahmep Посмотреть сообщение
Я только начал разбираться с языком, и пока пытаюсь переложить свои знания из ассемблера применительно к нему, найти какую-то аналогию.
Не стоит пытаться перекладывать откуда-то знания или пользоваться аналогиями (если ты не страдаешь ГСМ, конечно). Читай определения.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Поведение a[0] и a + 0 определяется через array-to-pointer conversion, а не наоборот
Вот именно. Поэтому гораздо логичнее считать, что в array-to-pointer conversion под "первым" понимается элемент, который с точки зрения [expr.add]/4 называется элементом 0, а не то, что под "первым" понимается элемент, чей адрес совпадает с адресом самого массива, как в
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В определении array-to-pointer conversion утверждение то том, что результирующий указатель указывает на первый элемент массива идет речь именно о самом первом элементе в физической последовательности элементов
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.06.2020, 08:41
Помогаю со студенческими работами здесь

как такое правильно писать? это ссылка на указатель?
#include &lt;iostream&gt; using namespace std; char *chch2 = &quot;hello&quot;; char*&amp; f() { char *&amp;chch3 = chch2; return...

Что лучше ссылка или указатель?
Что лучше - ссылка или указатель?

Не удалось найти имя типа или пространства имен пропущена директива using или ссылка на сборку
Доброе время суток.Есть код: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace...

Как ускорить работу. Ссылка или указатель
У меня следующая ситуация. Обработка изображений с EMGUCV. Объект Image весит очень много. Этот объект надо передавать в мой класс. ...

Имя массива как указатель
Используя имя массива как указатель, и применяя адресную арифметику выполнить задание (каждое задание оформить отдельной функцией). Дан...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
134
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru