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

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

12.06.2020, 14:18. Показов 12613. Ответов 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
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
12.06.2020, 14:28
Цитата Сообщение от cahmep Посмотреть сообщение
Пытаюсь понять что такое имя массива в С++! Указатель или ссылка?
Указатель.

Добавлено через 1 минуту
Цитата Сообщение от cahmep Посмотреть сообщение
К сожалению такой трюк не работает и получается что &arr==arr!
C++
1
arr == &arr[0]
0
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 14:37  [ТС]
Цитата Сообщение от Verevkin Посмотреть сообщение
Указатель.
почему тогда у этого указателя нет места в памяти?
в то время как например у указателя pArr из моего примера оно есть!
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
12.06.2020, 14:45
Цитата Сообщение от cahmep Посмотреть сообщение
почему тогда у этого указателя нет места в памяти?
Кликните здесь для просмотра всего текста

не понял, поясни
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
12.06.2020, 14:46
Цитата Сообщение от cahmep Посмотреть сообщение
или у меня неправильное представление об этих вещах?
Массив - это объект.
Имя массива неявно преобразуется к указателю на первый элемент.
Можно получить ссылку на массив (T(&)[n]).
Можно получить указатель на массив (T(*)[n]).
Но его нельзя изменить(всмысле присвоить другой массив).
2
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 15:15  [ТС]
Цитата Сообщение от Verevkin Посмотреть сообщение
не понял, поясни
насколько я понял указатель это такая же переменная которая находится в памяти и хранит адрес другой переменной на которую указывает.
теперь представим что массив это та же переменная на которую указывает указатель (только указывает не на все элементы массива разом а только на 1й). т.е. по идее должна быть такая же ячейка в памяти в которой хранится адрес 1го элемента массива. Раз есть ячейка в памяти, то у нее должен быть свой адрес!
0
Злостный нарушитель
 Аватар для Verevkin
10359 / 5774 / 1274
Регистрация: 12.03.2015
Сообщений: 26,686
12.06.2020, 15:45
Цитата Сообщение от cahmep Посмотреть сообщение
только указывает не на все элементы массива разом а только на 1й
Не на 1-й, а на 0-й.
Цитата Сообщение от cahmep Посмотреть сообщение
Раз есть ячейка в памяти, то у нее должен быть свой адрес!
Так и есть. Причом таких переменных может быть несколько.

0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
12.06.2020, 15:53
Цитата Сообщение от cahmep Посмотреть сообщение
Указатель или ссылка?
Ни то ни другое.
Цитата Сообщение от cahmep Посмотреть сообщение
Пытаюсь понять что такое имя массива в С++
Не поверишь - имя массива.
1
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 15:59  [ТС]
Цитата Сообщение от Verevkin Посмотреть сообщение
Так и есть. Причом таких переменных может быть несколько.
Воот!!!
но судя по твоей картинке ты создал динамический массив, а я про статический писал!
у статического массива вытащи адрес указателя точно также! у меня не получилось - как будто его нет.

Добавлено через 1 минуту
Цитата Сообщение от Croessmah Посмотреть сообщение
Ни то ни другое.
что тогда? твои варианты)
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
12.06.2020, 16:01
Цитата Сообщение от cahmep Посмотреть сообщение
что тогда?
Я ж написал, что имя массива - это имя массива.
Цитата Сообщение от cahmep Посмотреть сообщение
твои варианты
Выше пост #5 читал?

Давай по существую ты знаешь что такое массив?
Вот имя массива - это идентификатор, "обозначающий" данный массив.
Является ли идентификатор ссылкой или указателем? Нет, не является.
Является ли массив ссылкой или указателем? Нет, не является.

Как уже сказано выше, &arr - это адрес массива. И тип у него соответствующий.
Мы можем неявно получить указатель на первый элемент массива, при этом массив указателем не является.
C++
1
2
3
int arr[10];
int (*p1)[10] = &arr;//Адрес массива
int * p2 = arr;//Адрес первого элемента массива
Что вас удивляет в том, что адрес массива совпадает с адресом его первого элемента?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 16:08
cahmep,
Просто имя массива преобразуется в указатель на первый элемент массива в некоторых контекстах поэтому часто путают имя массива с указателем... Но само по себе имя массива это не указатель и не ссылка (как выше подметили).
0
248 / 70 / 9
Регистрация: 22.07.2018
Сообщений: 321
12.06.2020, 16:10
Цитата Сообщение от Croessmah Посмотреть сообщение
Что вас удивляет в том, что адрес массива совпадает с адресом его первого элемента?
Возможно то, что это не гарантируется стандартом...
0
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 16:31  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
Что вас удивляет в том, что адрес массива совпадает с адресом его первого элемента?
меня интересует как найти адрес переменной-указателя в которой хранится адрес нулевого элемента массива!
судя по всему такой переменной-указателя не существует, а есть просто адрес массива==адрес нулевого элемента arr...
но к этому имени массива, который как получается указателем по сути не является, применяется арифметика указателя каким то образом.
Цитата Сообщение от Croessmah Посмотреть сообщение
Мы можем неявно получить указатель
вот это неявно судя по всему ключевое слово
это как?

Добавлено через 5 минут
Цитата Сообщение от Undisputed Посмотреть сообщение
Просто имя массива преобразуется в указатель на первый элемент массива в некоторых контекстах поэтому часто путают имя массива с указателем... Но само по себе имя массива это не указатель и не ссылка (как выше подметили).
как это преобразование осуществляется? т.е. это компилятор каким то образом сам просто интерпретирует имя как указатель и позволяет работать с этим именем как с указателем?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
12.06.2020, 16:33
Цитата Сообщение от cahmep Посмотреть сообщение
Пытаюсь понять что такое имя массива в С++! Указатель или ссылка?
Имя массива - это имя объекта.

Судя по тому, что вы сейчас задаете вопросы эти, то вы не читали свою же тему? Что такое &arr + i
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 16:36
Цитата Сообщение от cahmep Посмотреть сообщение
как это преобразование осуществляется? т.е. это компилятор каким то образом сам просто интерпретирует имя как указатель и позволяет работать с этим именем как с указателем?
ну да.
например в случае когда массив передается в функцию а параметр указатель - тогда имя будет преобразовано в указатель
C++
1
2
3
4
5
6
7
8
9
10
11
12
void f(int* p)
{
    std::cout << "void f(int* p)\n";
}
 
int main()
{
    int arr[5];
    f(arr); // void f(int* p). имя массива преобразовано в указатель на его первый элемент
    std::cout << sizeof(arr); // выводит размер массива. имя массива не преобразовано в указатель на первый элемент
    // если бы имя массива являлось бы указателем, то sizeof(arr) всегда был бы равен sizeof(T*);
}
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
12.06.2020, 16:38
Цитата Сообщение от cahmep Посмотреть сообщение
как это преобразование осуществляется? т.е. это компилятор каким то образом сам просто интерпретирует имя как указатель и позволяет работать с этим именем как с указателем?
Точно так же, как здесь:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
struct int_array
{
    operator int*() {
        return (int*)(this); // pseudocode
    }
};
 
 
int main()
{
    int_array a;
    
    std::cout << a << std::endl; // a -> int*
    
    int * p = a; // a -> int*
    
    std::cout << p;
    
}
отличие только в том, что в примере пользовательское неявное преобразование, а в случае с массивом - стандартное.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 16:55
Цитата Сообщение от argcargv Посмотреть сообщение
Возможно то, что это не гарантируется стандартом...
Разве?
посмотрим на то что из себя представляет массив
11.3.4 Arrays
An object of array type contains a contiguously allocated non-empty set of N subobjects of type T
теперь посмотрим что такое адрес массива
6.6.2 Object model
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the addressof the first byte it occupies
то есть получается что когда мы берем адрес массива то получаем адрес первого байта этого массива.

Теперь посмотрим, что такое sizeof от array:
8.5.2.3 Sizeof
The sizeof operator yields the number of bytes in the object representation of its operand
...
When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element
Получается что адрес массива это адрес на его первый байт (первая цитата)
А элементы массива хранятся смежно (вторая цитата)
Размер же массива это n*sizeof(array) (третья цитата)

Тогда если &arr возвращает нам первый байт объекта (в данном случае массива) и все элементы хранятся смежно как видно выше и память массива состоит лишь из его элементов то можно сделать вывод что &arr адрес массива совпадает с адресом его первого элемента. Почему нет?

Добавлено через 1 минуту
Чем не гарантия? Объясните, пожалуйста.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
12.06.2020, 17:00
Цитата Сообщение от cahmep Посмотреть сообщение
А что же с именем массива? Ведь утверждается что это указатель на 1й элемент этого массива arr[0].
Вот вам пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
struct int_array4
{
    int a0;
    int a1;
    int a2;
    int a3;
    
    operator int*()
    {
        return &a0;
    }
    
};
 
int main()
{
    int_array4 arr = { 1, 2, 3, 4 };
    
    std::cout << &arr << ' ' << arr;
}
https://rextester.com/SABIM55794

Моделирует точно такое же поведение, какое вы видите в своем описании.
Теперь к вам вопросы:
1) arr теперь из-за этого стал ссылкой или указателем? Нет, как был объектом типа int_array4, так и остался.
2) Что удивительного, что &arr и arr дают один и тот же адрес? Объект arr содержит объект a0 первым и поэтому их адреса совпадают.
В случае в массивами вы видите те же самые закономерности.
2
0 / 0 / 0
Регистрация: 31.07.2014
Сообщений: 24
12.06.2020, 17:00  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Судя по тому, что вы сейчас задаете вопросы эти, то вы не читали свою же тему? Что такое &arr + i
нет, я прочел все ответы оттуда... кое что дошло, кое что нет. собственно из той темы и родилась эта.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
12.06.2020, 17:02
Цитата Сообщение от Undisputed Посмотреть сообщение
Размер же массива это n*sizeof(array)
Опечатка. Должно было быть n*sizeof(arrayElement)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.06.2020, 17:02
Помогаю со студенческими работами здесь

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

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


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

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