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

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

12.06.2020, 14:18. Показов 12607. Ответов 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
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
12.06.2020, 19:32
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от cahmep Посмотреть сообщение
Т.е. фактически указатель как таковой не обязательно должен в памяти храниться?
в чем же тогда его отличие от ссылки?
Ссылку тоже можно создать, а можно и не создать. Хотя вопрос о ссылках и указателях - бомба страниц на 100. Тут таких тем уже было не счесть.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12943 / 6810 / 1821
Регистрация: 18.10.2014
Сообщений: 17,235
12.06.2020, 19:33
Цитата Сообщение от cahmep Посмотреть сообщение
Т.е. фактически указатель как таковой не обязательно должен в памяти храниться?
"Указатель" и "адрес" в терминологии С и С++ - это синонимы. Разумеется, он не должен нигде храниться. С большего, в С и С++ "хранится" только то, что вы явно сами сохранили.

Цитата Сообщение от cahmep Посмотреть сообщение
в чем же тогда его отличие от ссылки?

Вопрос не ясен. При чем здесь вообще ссылки?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
12.06.2020, 19:39
Цитата Сообщение от cahmep Посмотреть сообщение
мне кажется мы вернулись к тому с чего начали)))
покажите мне для статического массива тот указатель который хранится где-то в памяти (т.е. у него есть собственная ячейка памяти со своим адресом) и содержит в себе адрес нулевого элемента.
Сами же писали что указатель получается как то неявно.
Я уже показывал.
Вот ваш пример
Цитата Сообщение от cahmep Посмотреть сообщение
C++
1
2
int a = 5; 
int* pa = &a;
Вот точно такой же пример для массива.
C++
1
2
int a[2] = {1,2}; 
int (*pa)[2] = &a;
Цитата Сообщение от cahmep Посмотреть сообщение
Сами же писали что указатель получается как то неявно.
Получение указателя - это результат вычисления (выражения с участием имени массива).
Давайте возьмем математику для примера.
Допустим у вас есть такое математическое выражение
x + n
Вы же не будете утверждать, что х хранит его результат?
Чтобы получить результат нужно сначала вычислить выражение.
1
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 19:42  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А возможно оно вообще существует только воображаемо, концептуально, т.е. на практике не возникает нигде вообще.
не такое я себе не могу представить и вряд ли так может быть)) (хотя черт его знает что там в наборе команд процессора может быть)
в регистрах это мне понятно и как раз не обязательно в памяти хранить указатель
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
12.06.2020, 19:44
cahmep, свой компилятор напиши и все вопросы отпадут.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12943 / 6810 / 1821
Регистрация: 18.10.2014
Сообщений: 17,235
12.06.2020, 19:50
Цитата Сообщение от cahmep Посмотреть сообщение
не такое я себе не могу представить и вряд ли так может быть)) (хотя черт его знает что там в наборе команд процессора может быть)
в регистрах это мне понятно и как раз не обязательно в памяти хранить указатель
Речь идет (в самом простейшем примере) о том, что если у вас есть массив char a[10], хранящийся по адресу 0x1000, и вы в своем коде хотите получить доступ к элементу a[5], то понятно, что в какой-то момент времени процессор должен будет вычислить адрес 0x1005 для доступа к элементу.

Но это совсем не значит, что сначала он должен будет взять адрес 0x1000, а затем прибавить к нему 5. Вполне возможно, что уже на этапе компиляции компилятор сразу поймет, что нужно осуществить доступ по адресу 0x1005 и все. То есть во время выполнения процессор сразу будет знать, ничего не вычисляя, что ему нужно прочитать данные с адреса 0x1005. При этом адрес 0x1000 (реальный адрес массива a) в программе вообще в явном виде нигде фигурировать не будет.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
12.06.2020, 19:56
Цитата Сообщение от cahmep Посмотреть сообщение
не такое я себе не могу представить и вряд ли так может быть))
Это запросто может быть.
Смотрите:
C++
1
2
3
4
5
6
7
8
9
int foo() {
    int a = 10;
    return a;
}
 
int main()
{
    int b = foo();
}
Давайте рассмотрим это с позиции "в лоб". У кого тут есть адреса с этой позиции.
a - имеет адрес.
Далее переменная а копируется в безымянную временную "переменную" через return. У нее тоже пусть будет адрес.
Далее эта переменная копируется в именованную переменную b, у нее, естественно, тоже есть адрес.

Итого 3 адреса.
Но если подумать, то второй адрес нам не нужен, потому что временное значение можно не размещать в памяти (в том числе и в регистрах). Зачем он нам нужен, если у нас есть a и есть b? Зачем нам этот посредник? Вот и получается, что временное значение имеет абстрактный характер. Оно естественно есть на этапе компиляции и мы производим с ним операции - оно участвует в выражении инициализации b. Но фактически адреса у него нет, потому что в реальности мы сразу копируем a в b

Добавлено через 6 минут
<уточнил формулировки> если вы читали старую версию - перечитайте.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
12.06.2020, 19:59
Цитата Сообщение от cahmep Посмотреть сообщение
не такое я себе не могу представить и вряд ли так может быть))
cahmep, в теме произошла инжекция другой темы. Вопрос о rvalue и временных объектах это не специфика указателей. Указатель не обязан создаваться. И указатель это не адрес. То есть, если его никто не создавал, то его нету. У массива есть адрес. Но указателя у него по праву рождения нет. Что касается адреса, то адрес это алгебраическое (арифметическое) значение указателя. Это часть его значения арифметической природы иными словами. Однако указатель это тип. Он предоставляет доступ с правами типа целевого объекта. Указатель void* хранит адрес массива, но не позволит индексацию.
Указатели lvalue нужно создавать, а rvalue создаются автоматически по мере надобности.
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
12.06.2020, 20:04
Цитата Сообщение от IGPIGP Посмотреть сообщение
адрес это алгебраическое (арифметическое) значение указателя
Тыц.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 20:14
Цитата Сообщение от argcargv Посмотреть сообщение
Оператор меньше определён для значений указателей, а не адресов
Интересно. А значение указателя это не адрес? Если нет, то что в таком случае проверяется на меньше при сравнении указателей?
А если значение указателя это все же адрес, то что не так ?
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
12.06.2020, 20:17
Цитата Сообщение от Undisputed Посмотреть сообщение
Интересно. А значение указателя это не адрес?
Прям сверху ссылка.
Цитата Сообщение от Undisputed Посмотреть сообщение
Если нет, то что в таком случае проверяется на меньше при сравнении указателей?
Вот.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 20:21
argcargv,
Там же написано про то каким будет результат сравнения указателей а не про то чем является значение указателя...

Добавлено через 26 секунд
Я имею ввиду зеленую часть
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
12.06.2020, 20:21
Цитата Сообщение от argcargv Посмотреть сообщение
адрес это алгебраическое (арифметическое) значение указателя
Тыц.
argcargv, вы слово value понимаете? Значение указателя и указатель как объект, это не одно и то же. Старайтесь выражать мысли связно, потому, что тыц это как-то уж слишком.
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
12.06.2020, 20:23
Цитата Сообщение от Undisputed Посмотреть сообщение
Там же написано про то каким будет результат сравнения указателей а не про то чем является значение указателя...
Под "прям сверху ссылка" имелось в виду сообщение Имя массива в С++ это указатель или ссылка?

Добавлено через 1 минуту
Цитата Сообщение от IGPIGP Посмотреть сообщение
вы слово value понимаете?
Да. Это "значение".
Цитата Сообщение от IGPIGP Посмотреть сообщение
Значение указателя и указатель как объект, это не одно и то же.
К.О.?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
12.06.2020, 20:28
argcargv, и ещё. Люди пишущие стандарт не считают слова достойными вниманию объектами
Every value of pointer type is one of the following:

(3.1)
a pointer to an object or function (the pointer is said to point to the object or function), or
тут комментарии излишни. А это позволяет вам и кому-либо еще, делать тыц
0
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 20:29  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Это запросто может быть.
я тут пока не копал) тоже интересная тема... не знаю точно как компилятор это переваривает, но вроде же передача значений в функцию и обратно через стек происходит... а стэк это участок памяти... работа со стеком идет через регистры, т.е. в какой-то момент наверное как раз там где "return a" участвуют и стек и регистры.
ну да ладно, это не вопрос данной темы) в след раз возможно к нему вернемся)

Ребят, всем спасибо!!! Разжевали!
Думаю понимание сложилось... теперь нужно переварить и утрясти)))
Ключевой момент моего недопонимания, наверное, как раз и было то что указатель, как оказалось, это не обязательно переменная в памяти.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
12.06.2020, 20:30
Цитата Сообщение от argcargv Посмотреть сообщение
К.О.?
Ну наверное. Но не для вас ведь. Вы же не различаете указатель как объкект и его значение, а стандарт вам помогает это делать. Тут десять копитанов очевидность замучаются.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
12.06.2020, 20:33
Все темы с вопросом "массивы и указатели" превращаются в свалку.

Особенно, если в них зашел IGPIGP
2
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
12.06.2020, 20:33
argcargv, вот полная цитата:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Что касается адреса, то адрес это алгебраическое (арифметическое) значение указателя. Это часть его значения арифметической природы иными словами. Однако указатель это тип.
вы прочтите весь текст и аргументируйте не односложно. Я не писал о том что такое тип указателя и какие они бывают. Я писал о том что указатель это НЕ адрес. А адрес это Часть значения.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 20:34
Цитата Сообщение от argcargv Посмотреть сообщение
Под "прям сверху ссылка" имелось в виду сообщение
а, я понял... тогда что вы скажете насчет этого?

C++
1
2
int arr[5];
int(*p)[5] = std::addressof(arr);
Returns:The actual address of the object...
то есть p здесь указатель а значение его адрес...
а адрес не входит в тот список который вы прислали
https://timsong-cpp.github.io/... sentence-8

тогда здесь если вам верить то получается что код выше содержит UB?
ведь выше получается что мы присваиваем указателю значение которое не входит в тот список...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.06.2020, 20:34
Помогаю со студенческими работами здесь

как такое правильно писать? это ссылка на указатель?
#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 весит очень много. Этот объект надо передавать в мой класс. ...

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


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

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
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