LINUX.ORG.RU

с++

 


0

2

не могу понять... нужна помощь. вобщем почему так нельзя?

#

int main(){
int array[2]{1, 3};
int array1[2]{2, 6};
int *p;
p=array; // array-это указатель на область памяти в которой может хранится первый элемент массива.
я его помещаю в указатель "p"

array=array1; 
array1=p; //тут обмениваю значениями два указателя , через третий.
посути теперь должно бы быть так:
for(int i=0; i<2; i++){
std::cout << array[i]// выведет 2 6
std::cout << array1[i]// выведет 1 3 
return 0;
}


#c

почему будет ошибка. почему так нельзя?

Ответ на: комментарий от fsb4000

Вот что говорит компилятор:

main.cpp:8:6: error: array type 'int [2]' is not assignable
array=array1;
~~~~~^
main.cpp:9:7: error: array type 'int [2]' is not assignable
array1=p;
~~~~~~^

и что тут неясного?

Нельзя массив присваивать, можешь считать, что массив это:

int* const array;
Но лучше просто понять, что массив и указатель, это разные типы...

fsb4000 ()

В с++ более строгий тайп чекинг, он любит материться на то, что формально работает, но является UB или подозрительными практиками™.

anonymous ()
Ответ на: комментарий от fsb4000

а я массив не присваиваю.... имя массива -это указатель на область памяти, где хранится его первый элемент. там же в комментариях я на писал.

я просто обмениваю указатели значениями. это же не запрещенно в плюсах?

linuxpc ()
Ответ на: комментарий от linuxpc

Как уже упомянули - «массив - это не указатель». Ты не можешь присвоить один массив другому таким образом.

Если уж используешь C-шные массивы в C++, то делай это хотя бы так:

#include <string.h>
#include <iostream>

int main(){
        const int size=2;
        const int memsize=size*sizeof(int);

        int array[size]{1, 3};
        int array1[size]{2, 6};
        int arraytmp[size];

        memcpy(arraytmp, array, memsize);
        memcpy(array, array1, memsize);
        memcpy(array1, arraytmp, memsize);

        for(int i=0; i<size; i++){
                std::cout << array[i] << " ";
        }
        std::cout << std::endl;
        for(int i=0; i<size; i++){
                std::cout << array1[i] << " ";
        }
        std::cout << std::endl;
        return 0;
}
Pinkbyte ★★★★★ ()
Ответ на: комментарий от linuxpc

я просто обмениваю указатели значениями. это же не запрещенно в плюсах?

Массив - это не только указатель, но и выделенная на него память. При твоём обмене, если бы он даже сработал - ты не выделяешь памяти на буфер для массива. В результате у тебя затерлось бы всё.

Pinkbyte ★★★★★ ()
Ответ на: комментарий от anonymous

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

linuxpc ()
Ответ на: комментарий от linuxpc

с точки зрения синтаксиса языка есть ошибка?

1.cpp: В функции «int main()»:
1.cpp:7:7: ошибка: некорректное присваивание массива
 array=array1;
       ^~~~~~

Звучит как ошибка на мой скромный взгляд

https://stackoverflow.com/questions/4118732/c-array-assign-error-invalid-arra...

Pinkbyte ★★★★★ ()
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от linuxpc

Если хочешь жонглировать указателями - выделяй память на все свои массивы через new/delete и жонглируй сколько угодно. Только следи за утечками

Pinkbyte ★★★★★ ()
Последнее исправление: Pinkbyte (всего исправлений: 2)
Ответ на: комментарий от Pinkbyte

так в том то и дело что там как бы без больших вопросов пока.

я хотел создать двумерный массив иным способом.



int main(){

int *array[2];//cоздаю массив указателей
int ar[3]{1, 2, 3}; // обычный массив.
array[0]=ar;
array[1]=ar;


//
посути создал двумерный не динамический массив.

//
но почему я не могу сделать так?
array=ar;
вот что родило эту тему.

return 0;
}

linuxpc ()
Последнее исправление: linuxpc (всего исправлений: 1)
Ответ на: комментарий от linuxpc

Потому что это не указатель, предназначенный для записи в него произвольных адресов, очевидно. Ты выделяешь в стеке память на массив и потому в твоём ar может храниться только адрес первого элемента твоего массива.

Reineke ()
Ответ на: комментарий от Reineke

а вот тут пожалуйста подробнее... значит имя массива это не такой указатель, как если бы я вдруг решил сделать так int *array, а потом array=new int [2];// посути же массив создался из обычного указателя. то есть array теперь имя массива, а было обычным указателем, с которым я мог делать вот так array=&a;

linuxpc ()
Ответ на: комментарий от linuxpc

Ну давай разберем по операциям тобой написанное.

array[0]
получаем адрес, который ты сохранил в нулевой ячейке array, то есть указатель на ar.
array[0] + 1
сдвигаемся относительно адреса ar на 1 элемент, то есть получаем адрес первого (считая с нуля) элемента массива ar
*(array[0] + 1)
разыменовываем наш адрес, то есть берем значение первой ячейки. Получаем 2. Всё логично. Никаких диких присвоений ты здесь не делал в отличии от выше описаных случаев.

Reineke ()

Нубы на ЛОРе

По сабжу: если говорить об адресной арифметике, ТО адрес массива это адрес его первого элемента. Потом ты можешь аккуратно ходить по массиву с помощью инкремента/декремента.

А вообще http://givi.olnd.ru/kr/05.html читать до Просветления.

Без понимания того, что описано по ссылке я бы тебя к экзамену не допустил.

А вообще тебе бы про ассемблер почитать, чтобы знать какая бывает адресация и как ПК работает с адресами переменных заданного типа.

P.S.

но почему я не могу сделать так? array=ar; вот что родило эту тему

Потому что, когда нужно обработать элементы массива их следует обрабатывать поштучно, в цикле. Плюс, как уже писали выше, ты не выделяешь память для новых подмассивов.

Twissel ★★★★★ ()
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от linuxpc

В случае int array[n] - ты выделяешь память только для n элементов массива, при этом дополнительно ячейка для адреса условно не выделяется. В случае же int *array и так далее, ты выделяешь сначала память под указатель, а потом ещё дополнительно для самого массива. Точно так же, например, двухмерный массив и массив указателей - это разные структуры, т.к. в первом случае (если мы, например создаём двухмерный массив вида arr[n][m]) создаётся массив размера n * m и всё. А в массиве указателей ты ещё дополнительно выделяешь память для n указателей. Более подробно читай в K&R в главе 5.

Reineke ()
Ответ на: комментарий от Reineke

ребята, так я хочу понять, что мешает мне сделать это дикое присвоение.

поэтому я задаю эти вопросы. сам не могу понять. вроде бы ничего не мешает это сделать, но не делается.

почему? простая операция же с указателями. уже выше привел пример, как делаю из обычного указателя имя массива . все работает.

тогда почему не могу сделать так? array=ar. ведь array-это указатель на массив, который содержит указатели. то есть он был создан вот так *array[2]; и значит он содержит адрес первого элемента этого массива, то есть указателя. // обратите на это внимание// и теперь я хочу чтобы этим первым указатем был ar. то есть это указатель на первый элемент массива.

что неправильно?

linuxpc ()
Ответ на: комментарий от linuxpc

В очередной раз: массив не указатель. Присваивать можно уеазателю, а имя массива не является lvalue-указателем.
В качестве rvalue-указателя на начальный элемент имя массива можно использовать только потому, что в этом случае выполняется автоматическое преобразование из int[n] в int*.

bormant ★★★★★ ()
Последнее исправление: bormant (всего исправлений: 1)
Ответ на: комментарий от linuxpc

ведь array-это указатель на массив, который содержит указатели

Ннееет. Это не указатель. Это массив указателей. Потому и не можешь. Прислушайся к совету Twissel. У тебя каша с теорией, потому ты и путаешься на практике. А потому нет смысла дальше идти пока ты для себя не усвоишь, что массив != указатель на массив. У них разная механика работы, несмотря на то, что некоторые операции применимы к обеим сущностям. Это заложено в синтаксис языка.

Reineke ()
Ответ на: комментарий от linuxpc

что неправильно?

Для начала элементы в массив копируются поштучно, см. выше.

Т.е. компилятор Си за тебя не посчитает что у тебя массивы одинакового размера и их можно один к одному скопировать в новый двумерный массив.

Ты сам должен ему указать, что куда копируется и как. С/Си++ это тебе не Питон тут многое приходится делать ручками и думать, что ты делаешь.

Twissel ★★★★★ ()
Ответ на: комментарий от Pinkbyte

https://habr.com/post/251091/

Редкостное говно.

сейчас я вам объясню, как это на самом деле устроено!
...
Этот принцип («выражение, являющееся переменной — ссылка») — моя выдумка. Т. е. ни в каком учебнике, стандарте и т. д. я этот принцип не видел.

Автор обещает разобрать якобы «тонкие» понятия, а начинает нести полную чушь. Причём даже не скрывает, что это отсебятина.

anonymous ()
Ответ на: комментарий от anonymous

Я не зря уточнил «если не хочешь читать стандарт». ТС(судя по задаваемым вопросам) явно не читал и вполне возможно и не собирается. А если он хочет набивать шишек сам, то пусть не удивляется что ему будут присылать первые ссылки из гугла, которые он не мог нагуглить сам :-)

TL;DR: саму статью на хабре я не читал и не имею абсолютно никакого понятия о том, насколько она хороша или плоха. А впрочем теперь немного немножко имею - у меня есть один отрицательный отзыв от анонимуса.

Pinkbyte ★★★★★ ()
Ответ на: комментарий от Pinkbyte

ладно, тут жизнь научит.

просьба: еще уточните одну деталь.

пишут, что строка в с++ это массив символов. я пытался взять с нее адрес, как адрес массива, но нифига не вышло. что такое string в плюсах? это явно не массив символов. что же это? string st=«abc»; что это?

linuxpc ()

Изучи тему «Указатели и const»

int sloth = 3;
const int *ps = &sloth;      // указатель на const int
int * const finger = &sloth; // const-указатель на int

Массив можно сравнить с const-указателем. Можно изменять значения элементов массива. Но сам указатель нельзя изменить.

Ты хочешь поменять указатели (на массивы, через имена массивов) местами. Это нельзя делать для const-указателей.

neon1ks ★★ ()
Последнее исправление: neon1ks (всего исправлений: 2)
Ответ на: комментарий от linuxpc

Попробуй пересесть на чистый Си, разберись для начала с ним и не насилуй плюсы, а они не будут насиловать тебя. Когда будешь понимать как работают примитивные структуры, тогда пойдёшь в няшный кресто-мир со свистоперделками, классами, шаблонами и прочим. А пока у тебя и люди и кони, как говорится. Массив символов - это char * - обычный массив чаров, заканчивающийся нуль-терминатором (последний элемент массива должен быть равен нулю). Так, например, хранятся и литеральные строки (когда ты пишешь в коде какой-то текст в кавычках). А string - это объект соответсвующего класса в плюсах, более безопасный и более удобный в некоторых случаях. Общего с массивом чаров у него только то, что и там и там как правило, собственно строки хранятся.

Reineke ()
Ответ на: комментарий от neon1ks

я правильно понимаю?

int *p; // тут создан указатель.
//как только я его свяжу с именем массива , он станет const указателем/
p=new int [2]// указатель 'p' стал указателем const


так?
linuxpc ()
Ответ на: комментарий от linuxpc

Нет, здесь обычный указатель. Здесь ты можешь попробовать провернуть свое дело. Поменять местами указатели. Но только надо понимать, что ты делаешь, чтобы не «прострелить себе ногу».

neon1ks ★★ ()