2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 C/С++ массивы, указатели
Сообщение04.09.2016, 05:24 


03/04/14
303
Есть массив:
int a[2] = {0,1};

Почему нижеприведенные строчки указывают на один и тот же адрес?
cout<<a<<endl;
cout<<&a<<endl;

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 06:20 
Заслуженный участник


04/05/09
4582
По стандарту имя массива даёт адрес первого элемента массива, с соответствующим типом. &a даёт адрес всего массива, с соответственно другим типом.
Стандарт, кажется, нигде не требует, чтобы первый элемент массива лежал с самого начала, с тем же адресом, что и у всего массива. Тем не менее, нет особого смысла делать иначе, т.е. обычно адрес массива и адрес его первого элемента равны. Но я не удивлюсь, если на какой-нибудь древней архитектуре типа Cray в начале массива лежит его описание - размеры и т.д., и адрес первого элемента будет отличаться. В таком случае ваш код выведет два разных адреса.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 12:37 


03/04/14
303
venco в сообщении #1148898 писал(а):
По стандарту имя массива даёт адрес первого элемента массива, с соответствующим типом. &a даёт адрес всего массива, с соответственно другим типом.


Погодите, я рассуждал так, если взять пример с просто указателями:

int a = 1;
int *pa = &a;

cout<<pa<<endl;
cout<<&pa<<endl;

pa - указатель на int, как и имя массива - указатель на int.
pa хранит адрес a, сама же переменная pa - располагается по другому адресу.


Теперь аналогично с массивом:

bayah в сообщении #1148896 писал(а):
Есть массив:
int a[2] = {0,1};

cout<<a<<endl;
cout<<&a<<endl;


a - указатель на int
Сама же переменная указателя должна располагаться по какому то адресу, очевидно отличному от того, что хранится в a?

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 12:46 
Аватара пользователя


18/06/12

499
планета Земля
venco в сообщении #1148898 писал(а):
&a даёт адрес всего массива, с соответственно другим типом.
В чём может быть разница между типом элемента и типом массива, если в сях все элементы массива обычно имеют один тип?

bayah в сообщении #1148896 писал(а):
Почему нижеприведенные строчки указывают на один и тот же адрес?
Насколько я понимаю синтаксис, вывести значение переменной а и вывести то, что лежит где-то в памяти по адресу, который записан в переменной а - одно и то же действие.

-- 04.09.2016, 11:48 --

bayah в сообщении #1148962 писал(а):
Сама же переменная указателя должна располагаться по какому то адресу, очевидно отличному от того, что хранится в a?

Только после того, как вы её такую заведёте :wink:

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:08 
Заслуженный участник


02/08/11
6874
bayah в сообщении #1148962 писал(а):
a - указатель на int
Указатель, но не переменная. Просто компилятор разрешает вместо выражения (которое, как вы можете видеть, именно выражение, а вовсе не переменная) &a[0] писать просто a, так как это не приводит к неоднозначности. То есть в одних случаях a в коде — это именно переменная, но переменная-массив, а не переменная-указатель, а в других случаях — когда подразумевается &a[0] — это именно выражение, имеющее своим значением указатель на начало массива, но не переменная a.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:13 
Заслуженный участник


27/04/09
28128
Eimrine в сообщении #1148965 писал(а):
В чём может быть разница между типом элемента и типом массива, если в сях все элементы массива обычно имеют один тип?
Приехали. :-) В типе и разница. a vs. a[] (ну или там a[n] какое-нибудь и т. п.).

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:23 


03/04/14
303
warlock66613 в сообщении #1148975 писал(а):
bayah в сообщении #1148962 писал(а):
a - указатель на int
Указатель, но не переменная. Просто компилятор разрешает вместо выражения (которое, как вы можете видеть, именно выражение, а вовсе не переменная) &a[0] писать просто a, так как это не приводит к неоднозначности. То есть в одних случаях a в коде — это именно переменная, но переменная-массив, а не переменная-указатель, а в других случаях — когда подразумевается &a[0] — это именно выражение, имеющее своим значением указатель на начало массива, но не переменная a.


Забавно... указатель, но не переменная...
Ну да, если сделать промежуточную переменную указатель на int таким образом:
int a[2] = {0,1};
int *pa = &a[0];

cout<<pa<<endl;
cout<<&pa<<endl;

, то тут уже разные адреса выдаются естественно, но...что тогда такое имя массива? Если имя массива - а, то уже просто обращение к a есть выражение? А где сама переменная тогда? Ее адрес невозможно получить?)

-- 04.09.2016, 20:26 --

Eimrine в сообщении #1148965 писал(а):
bayah в сообщении #1148896

писал(а):
Почему нижеприведенные строчки указывают на один и тот же адрес? Насколько я понимаю синтаксис, вывести значение переменной а и вывести то, что лежит где-то в памяти по адресу, который записан в переменной а - одно и то же действие.


Как это одно и то же?
Если а - указатель, то
cout<<a;
выведет значение которое записано в а - какой-то адрес
А вот
cout<<*a
выведет то, что лежит по адресу записанному в а.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:32 
Заслуженный участник


04/03/09
906
Eimrine в сообщении #1148965 писал(а):
В чём может быть разница между типом элемента и типом массива, если в сях все элементы массива обычно имеют один тип?

Вот пример.
Используется синтаксис C++
#include <iostream>
using namespace std;

int main() {
        int a[10];
        cout << typeid(a).name() << endl;
        cout << typeid(&a).name() << endl;
        cout << a << "  " << &a << endl;
        cout << a + 1 << "  " << &a + 1 << endl;
        return 0;
}

Результат выполнения:
Код:
int [10]
int (*)[10]
00BEFF04  00BEFF04
00BEFF08  00BEFF2C

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:33 
Заслуженный участник


02/08/11
6874
bayah в сообщении #1148983 писал(а):
Забавно... указатель, но не переменная...
Да. "Указатель" — это просто тип, так же как "целое", например. Выражение 10 + 20 имеет целочисленный тип и значение (30), но не является переменной. Во время выполнения программы это значение скорее всего (но не обязательно) лежит в оперативной памяти — то есть по сути в некоторой переменной, но это вспомогательная, временная переменная и она недоступна программисту (потому что её может и вообще не быть — смотря какой исполняемый код создаст компилятор). С указателями всё то же самое.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:35 
Заслуженный участник


27/04/09
28128
bayah в сообщении #1148983 писал(а):
но...что тогда такое имя массива?
А с остальными именами вы разобрались, значит?

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:42 
Заслуженный участник


02/08/11
6874
bayah в сообщении #1148983 писал(а):
Если имя массива - а, то уже просто обращение к a есть выражение? А где сама переменная тогда? Ее адрес невозможно получить?)
Переменная — это, по сути, кусок памяти. Его адрес можно получить, так же, как и для любой другой переменной: &a, но численно он обычно совпадает со значением выражения a, хотя типы разные:
если переменная a имеет тип int [20], то есть это массив $20$ целых,
то выражение &a имеет тип int (*)[20], то есть указатель на массив $20$ целых,
а выражение a имеет тип int *, то есть указатель на целое.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:45 
Заслуженный участник


04/03/09
906
bayah в сообщении #1148983 писал(а):
А где сама переменная тогда? Ее адрес невозможно получить?)

Возможно, вам поможет понимание, где в памяти во время выполнения программы какие переменные располагаются и чему равно их значение.
Случай 1:
Используется синтаксис C
int main() {
        int b;
}

У вас на стеке создается переменная b. То есть, есть ячейка в памяти, в которой записано значение этой переменной.
Случай 2.
Используется синтаксис C
int main() {
        int *a = new int[10];
}

У вас аллоцируется в куче участок памяти размером 40 байт, в котором будут записаны значения элементов массива, адрес первого элемента записывается в переменную a, которая на стеке. То есть, кроме самого массива, есть еще и ячейка памяти, где записан адрес этого массива.
Случай 3.
Используется синтаксис C
int main() {
        int a[10];
}

В этом случае у вас на стеке создается массив размером 40 байт. При этом адрес этого массива никуда не записывается. В плане расположения переменных в памяти этот случай абсолютно идентичен такому:
Используется синтаксис C
int main() {
        int a0,a1,a2,a3,a4,a5,a6,a7,a8,a9;
}

Переменные есть, но их адреса ни в какие другие переменные не записаны, потому что мы других переменных и не завели.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:49 
Заслуженный участник
Аватара пользователя


28/07/09
1178
Да уж, такой код может неподготовленному человеку надолго вынести мозг. Вроде как разименовываем один и тот же адрес, а поди ж ты..
Используется синтаксис C++
#include <iostream>                                                                  
                                                                                     
using namespace std;                                                                
                                                                                     
int main()                                                                          
{                                                                                    
    int a[2] = {0, 1};                                                              
    cout << a << endl;                                                              
    cout << &a << endl;                                                              
                                                                                     
    cout << *a << endl;                                                              
    cout << *&a << endl;                                                            
    return 0;                                                                        
}

Используется синтаксис Bash
0x7ffedc3dbb50
0x7ffedc3dbb50
0
0x7ffedc3dbb50
 

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 14:05 
Аватара пользователя


18/06/12

499
планета Земля

(Оффтоп)

Legioner93 в сообщении #1148998 писал(а):
а поди ж ты..
Мне почему-то вспомнилась ошибка на миллиард долларов :mrgreen:


-- 04.09.2016, 13:17 --

bayah в сообщении #1148983 писал(а):
что тогда такое имя массива
Выражение, которое во время компиляции заменяется указателем на массив.

-- 04.09.2016, 13:34 --

bayah в сообщении #1148962 писал(а):
Сама же переменная указателя должна располагаться по какому то адресу, очевидно отличному от того, что хранится в a?
Если я вас правильно понял, то "переменная указателя" - просто макрос, который ищет все вхождения а и заменяет их на автосгенерированный указатель, который и указывает на массив. В откомпилированной программе имена переменных не сохраняются.

 Профиль  
                  
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 14:58 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Legioner93
Вы разыменовываете не один и тот же адрес. Вот если вы запишете *reinterpret_cast<int *>(&a), тогда вы получите тот же 0.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 33 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group