2014 dxdy logo

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

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




На страницу 1, 2, 3  След.
 
 C/С++ массивы, указатели
Сообщение04.09.2016, 05:24 
Есть массив:
int a[2] = {0,1};

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

 
 
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 06:20 
По стандарту имя массива даёт адрес первого элемента массива, с соответствующим типом. &a даёт адрес всего массива, с соответственно другим типом.
Стандарт, кажется, нигде не требует, чтобы первый элемент массива лежал с самого начала, с тем же адресом, что и у всего массива. Тем не менее, нет особого смысла делать иначе, т.е. обычно адрес массива и адрес его первого элемента равны. Но я не удивлюсь, если на какой-нибудь древней архитектуре типа Cray в начале массива лежит его описание - размеры и т.д., и адрес первого элемента будет отличаться. В таком случае ваш код выведет два разных адреса.

 
 
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 12:37 
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 
Аватара пользователя
venco в сообщении #1148898 писал(а):
&a даёт адрес всего массива, с соответственно другим типом.
В чём может быть разница между типом элемента и типом массива, если в сях все элементы массива обычно имеют один тип?

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

-- 04.09.2016, 11:48 --

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

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

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

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

 
 
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:23 
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 
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 
bayah в сообщении #1148983 писал(а):
Забавно... указатель, но не переменная...
Да. "Указатель" — это просто тип, так же как "целое", например. Выражение 10 + 20 имеет целочисленный тип и значение (30), но не является переменной. Во время выполнения программы это значение скорее всего (но не обязательно) лежит в оперативной памяти — то есть по сути в некоторой переменной, но это вспомогательная, временная переменная и она недоступна программисту (потому что её может и вообще не быть — смотря какой исполняемый код создаст компилятор). С указателями всё то же самое.

 
 
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:35 
bayah в сообщении #1148983 писал(а):
но...что тогда такое имя массива?
А с остальными именами вы разобрались, значит?

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

 
 
 
 Re: C/С++ массивы, указатели
Сообщение04.09.2016, 13:45 
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 
Аватара пользователя
Да уж, такой код может неподготовленному человеку надолго вынести мозг. Вроде как разименовываем один и тот же адрес, а поди ж ты..
Используется синтаксис 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 
Аватара пользователя

(Оффтоп)

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 
Аватара пользователя
Legioner93
Вы разыменовываете не один и тот же адрес. Вот если вы запишете *reinterpret_cast<int *>(&a), тогда вы получите тот же 0.

 
 
 [ Сообщений: 33 ]  На страницу 1, 2, 3  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group