![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
может , но рабочий объясни плз в чем разница! -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Рабочий он, но только с одномерным массивом, потому что реализачия действительно на большинстве компилеров почти одинакова. На примере многомерного попробую обьяснить. Как мы знаем, многомерный массив после аллокации и инициализации будет выглядеть так: char **x=new char *[5]; for(int i=0;i<5;i++) { x[i]=randomstring();//предположим, эта функция возвращает char* } [0]->['3456345'] [1]->['1234'] [2]->['etzertz'] [3]->['78904567'] [4]->['7890789'] А если определить char y[5][10]; То выделен на весь массив будет один участок памяти. (одномерный массив) [0,1,2,3,4,5,6,..50] при этом если обращаемся к динамическому х х[2][3], то берётся третья буква второго элемента, а если обращаемся к "статическому" y y[2][3], то index элемента в массиве будет вырешан. например 2*5+3; При этом каждый компилер может это делать по разному. Как именно, стандартом не определено. Вполне возможно, что "статический" не будет отличатся от динамического, но в принципе компилер может делать из [] любую структуру. Поэтому после "преобразования" одного типа массива в другой, ошибки при доступе неизбежны. char **c=(char**)y; Такого например уже хороший компилер сделать не даст, но компилер всегда можно обмануть (как ты и сделал). С одномерными, как я уже сказал, проще, но лучше не привыкать к таким вещам. |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
sergejzr, я ниче не понял
имхо это не правомерно т.к. это дин. массив чаров, а ты туда указатель на чар имхо я не обманывал , а преобразовал к нужному типу. этого я вообще не понял, имхо все массивы в памяти преобразуются в одномерный массив, а уж динамика это или статика имхо для проги все равно , разница где это размещается, имхо -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
да не спорю char s[] и char *s[] это разные вещи, но это понять не могу
мне не понятна в чем разница между char** и char [][] я имею ввиду для дальнейшего использования , ане для инициализации? -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Сейчас, разделю темку, а то оффтоп пошёл
ПС: Ну представь, функция у тебя void test(char**x){} а ты ей y[][] передал Набросал примерчик. Смотри то, что выделено тире
Так что char*,char**, и char[][] это всё разные вещи и преображать одно к другому можно лишь точно понимая, что ты делаешь. |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
вот я ее и посеял имхо не корректное преобразование т.к. при обращении tricky[i][z] мы должны знать размерность массива , а при передаче tricky=(char **)y; мы по минимуму теряем 1 размерность , и я такого нигде не видел, везде где идет передача массива более 1 размерности , тогда делают типа такого tricky[][5] тогда понятно будет проге что у нас массив какая то куча строк и 5 столбцов (ну или наоборот) имхо приобразование как я делал , никакого обмана не несет , а твой пример серьйозно обманывает и компилятор и себя , плюс приводит к неработоспособности проги! -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
char** и char[][] - разные типы - в этом вся разница, другое дело, что их использование тесно переплетается -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
MAKCim, давай без пространственных фраз в чем они разные? -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Ты там по живому режешь и просто везёт, что в данном случае реализация char* и char[] совпали. А что если компилятор из char[] вообще свой класс делает у которого оператор[] переложен? Стандарт такое позволяет делать. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
что значит в чем? char** - двойной указатель на char - указывает на указатель, который содержит адрес char char[][] - тип двумерного массива - нельзя неявно преобразовать к char** может еще указатель и массив одно и то же? Это сообщение отредактировал(а) MAKCim - 28.9.2006, 13:41 -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
не понял объясни в чем разница между массивами и указателями в си? -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| EvgenZ |
|
|||
![]() Freedom in me ![]() ![]() Профиль Группа: Участник Сообщений: 407 Регистрация: 3.8.2006 Репутация: 1 Всего: 11 |
А я думал, что имя массива и есть указатель... И что кому как удобнее тот так и делает (* или [] )
-------------------- <удалено администрацией форума> |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Я же специально во втором посте этой теме это попытался расжевать char ** [0]->['3456345'] [1]->['1234'] [2]->['etzertz'] [3]->['78904567'] [4]->['7890789'] Для реализации массива 5,10 необходимо 5+5*10=55 байт 5 байт указателей и 50 байт содержимого причём содержимое может частями находится в любом месте RAM. А у char[5][10] всего 50 байт и все лежат массивом подряд. Добавлено @ 13:55 Массив - структурированный участок памяти. Указатель - ячейка памяти.
Массив никуда "указывать" не может. В отличии от указателя, который как раз на массив может также указывать. Я не могу больше обьяснять. Просто не знаю как понятнее сказать.. Знаешь такой класс Vector? В нём тоже есть оператор [] и работает как массив, но Vector это КЛАСС и преобразовать его в массив путём обьявления - приведёт к неопределённым последствиям. |
|||
|
||||
| EvgenZ |
|
|||
![]() Freedom in me ![]() ![]() Профиль Группа: Участник Сообщений: 407 Регистрация: 3.8.2006 Репутация: 1 Всего: 11 |
Мне в голову пригшла мысль, т.е. если у меня есть массив [][] , то я могу обращаться к нему с помощью указателей ** , а если он представлен у меня **, то я немогу использовать [][]. Правильно?
-------------------- <удалено администрацией форума> |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Это разные вещи и нельзя ни того, ни другого. В примере кода я показал, как из char** правильно сделать char[][] - копированием при инициализации. И как неправильно - преобразованием (char**);
|
|||
|
||||
| MAKCim |
|
||||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
Блин, ну открой K&R и посмотри Вся фишка в том, что если два понятия можно использовать схожим образом - это еще не значит что это одно и то же Массив - это последовательность элементов одного типа (располагаются в памяти друг за другом) Указатель - переменная, содержащая виртуальный адрес какого-то объекта Касаясь отличий, да возьмем хотя-бы такой пример
Хотя бы это показывает, что char* и char[] - разные понятия Добавлено @ 14:10
Первое неправильно, второе правильно p[i][j] ~ *(*(p+i)+j); но char** p = array неправильно синтаксически если array это char[2][2] к примеру, т к разные типы можно конечно с помощью (char**) или в С++ с помощью reinterpret_cast<char**> привести но зачем? -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||||
|
|||||||
| SergeCpp |
|
||||||
![]() ![]() ![]() Профиль Группа: Участник Сообщений: 955 Регистрация: 8.8.2005 Где: At Home Репутация: 15 Всего: 124 |
...из книги Сергея Деревяго C++ 3rd: комментарии
Встроенные в C++ типы низкого уровня, такие как указатели и массивы, имеют соответствующие операции, поэтому мы можем записать:
Ну, если к делу подойти формально, то записать мы так не можем. Вот что говорит об этом д-р Страуструп:
Так в чем же нарушается эквивалентность? По стандарту C++ мы имеем следующие эквивалентные преобразования: &vc1[200] -> &(*((vc1)+(200))) -> &*(vc1+200) Действительно ли равенство &*(vc1+200) == vc1+200 неверно?
Спешу вас успокоить, что на практике в выражении &*(vc1+200) некорректное разыменование *(vc1+200) практически никогда не произойдет, т.к. результатом всего выражения является адрес и ни один серьезный компилятор не станет выбирать значение по некоторому адресу (операция разыменования) чтобы потом получить тот же самый адрес с помощью операции &. |
||||||
|
|||||||
| likehood |
|
|||
|
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
||||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
т.е int y(char[]) это то же, что и int x(char*) ? (я уже про многомерные не говорю) при вызове y массив скопируется в стек полностью, при вызове x скопируется только указатель на него. |
|||
|
||||
| Romikgy |
|
||||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
еще вопросы Добавлено @ 15:24 Давайте народ определимся о каких вещах мы говорим, об объявлении переменых , или об передаче переменых в ф_цию? -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
||||
|
|||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Перестаньте приводить ассемблерские кода. Это не доказательство никакое!!!
Они разные получаются в зависимости от оптимизатора и конкретного компилера. Если у задачи существует оптимальное решение и оптимизатор его знает, то он любой код, приводящий это решение, скомпилит в одинаковый машинный код. Это не значит, что измени условие задачи, вывод останется тем же.!! Зачем там memset, если место ты уже [] выделил? |
|||
|
||||
| MAKCim |
|
||||||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
В любом случае char* - char[], так же как и char** - char[][] - разные понятия При вызове функции в стек копируется адрес первого элемента массива Т. е компилятор сам осуществляет преобразование, массива в адрес первого элемента, создавая впечатление эквивалентности этих понятий (указателя и массива). Но они не эквивалентны как не крути - массив - это массив, переменная - это переменная! Добавлено @ 15:32
В стеке переменные по-умолчанию не инициализируются 0
Здесь я бы не спорил, т. к если в сигнатуре функции мы пишем int a[20]/[], то передается все равно указатель -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
||||||
|
|||||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
А зачем так писать, если не инициализируешь? написал бы второй строкой sx[0]='s'. Выделять память там полюбому не надо. |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
мемсет у мя обнуляет выделеную память Добавлено @ 15:49 а куда тогда писать? мы выделяем память или в хипе динамически, или в стеке если массивом -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Зачем? Но это к делу отношения не имеет.. Естесственно компилер любой код приведёт к указателям и числам. Как и классы ООП, массивы являются лишь обёрткой следующего уровня. Добавлено @ 15:52 чар[20] - ты уже этим память выделил. Туда и писать. |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
да но посмотри что в этих чарах лежит сразу после выделения дык а кто юзает код проги , компиляторы -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
Какайя разница, что там лежит? Мусор какой нибудь. Добавлено @ 16:11 Убери мемсет из кода. Ничего не изменится. |
|||
|
||||
| likehood |
|
|||
|
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
да а я про них тоже не говорил в том то и дело что нет, т.к. в большинстве случаев это не требуется, а память жалко
все таки массив - это структура данных в памяти, она никуда не преобразовывается. Просто когда мы передаем массив в функцию всегда передается его адрес, сама же функция не может определить чем был исходный массив: обычным статическим масивом или указателем, ссылающимся на динамич. массив. В этом смысле при передаче одномерного массива разницы между массивами и указателями нет. p.s. с многомерными массивами все не так просто |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
согласен , но имхо лучше когда обнуляешь -------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
я немного не так выразился -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 19 Всего: 360 |
||||
|
||||
| likehood |
|
|||
|
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
если что-то нехорошее может произойти, оно обязательно произойдет.
поэтому иногда лучше перестраховаться (хотя в данном случае и не обязательно). |
|||
|
||||
| EvgenZ |
|
|||
![]() Freedom in me ![]() ![]() Профиль Группа: Участник Сообщений: 407 Регистрация: 3.8.2006 Репутация: 1 Всего: 11 |
baronp, прав массив передается в функцию как указатель.
-------------------- <удалено администрацией форума> |
|||
|
||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
-------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| UnrealMan |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
char[] – это не тип, а обозначение. Для аргумента функции оно означает абсолютно то же самое, что и char *. Типом же является char[n], где n – некоторая константа.
Под массивом подразумевался тип. И преобразование типа действительно имеет место. Это ты рассказываешь про функции, аргументы которых объявлены как указатели. Было бы странно ожидать от них чего-то другого. Для того, чтобы передать в функцию массив (а не просто указатель на его первый элемент) используется ссылка на массив:
Разумеется, никакого копирования элементов при передаче массива по ссылке не происходит. Если требуется передать массив произвольного размера, то можно воспользоваться шаблоном:
Так что шаблонная функция вполне может определить, чем был исходный массив. А списком инициализации не судьба?
Это сообщение отредактировал(а) UnrealMan - 1.10.2006, 20:37 |
||||||||
|
|||||||||
| Romikgy |
|
|||
![]() Любитель-программер ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7326 Регистрация: 11.5.2005 Где: Porto Franco Odes sa Репутация: 8 Всего: 146 |
-------------------- Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. |
|||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Если массив будет полем класса, то такой подход не пройдёт. Но даже в этом случае прямое применение memset – не лучшее решение. Надёжнее будет написать коротенькую функцию-шаблон для обнуления:
Теперь не нужно указывать точный размер массива (функция сама его выведет). |
|||
|
||||
| Athlon |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 15.1.2006 Где: Украина:: Запорож ье Репутация: нет Всего: нет |
Когда я начинал читать эту тему, то думал, что четко представляю себе различие между передачей параметров по ссылке(char*) и по значению(char[]), а теперь выяснил, что в обоих случаях происходит передача по ссылке и если я изменю значения массива переданого функции, то эти изменения останутся после выхода из функции, например так:
Т.е. на выходе я получу '1', есть ли еще где-то такие фишки(параметр переданый по значению передается по ссылке) P.S. это конечно отвратительный стиль менять объекты переданные по значению, но мне любопытно узнать есть ли еще такие фокусы Это сообщение отредактировал(а) Athlon - 29.9.2006, 15:52 |
|||
|
||||
| Oleg_Ci |
|
||||
![]() Friend ![]() ![]() Профиль Группа: Участник Сообщений: 485 Регистрация: 28.5.2006 Где: Новосиб.обл. Репутация: 3 Всего: 30 |
Смотрим "внутренности" массивов и указателей на указатели
Пытаюсь понять разницу между массивами и указателями и прожку для "разгдядывания" написал. Запускаете её и она выводит содержимое массива в виде таблицы (число -> строка). Число - это адрес начала строки. Первая таблица выводит параметры массива ( char[][] ), а вторая параметры указателей на указатели ( char ** ). После таблицы выводит ещё пораметры: 1) "Length str2 - str1 (число) " - это количество байт между началом первой строки и второй. Пример: для массива [10][10] расстояние равно 10(т.е. длинна первой строки, а за ней сразу вторая), а для указателей то 56 то 72). 2) "char **a + 10 -> (строка) " - это выводится строка, куда указывает "указатель смещённый на длинну строки(10)" от начала первой строки, т.е. в случае с массивом char a[10][10] выражение a+10 - будет указывать на вторую строку массива, а в случае с указателями небудет. 3) "Size matrix = (число) " - разница между адресами первого элемента массива и последним. Т.е. для размерности массива 10х10 &a[0][0] - &a[9][9] = 99, т.е. 100 символов (ноль тоже число), а для указателей(char**) &a[0][0] - &a[9][9] = 657 ! Вобщем так получается:
|
||||
|
|||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |