Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разница между [] и * 
:(
    Опции темы
Romikgy
Дата 27.9.2006, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  27.9.2006,  12:05 Найти цитируемый пост)
это не хороший совет.

может , но рабочий smile
Цитата(sergejzr @  27.9.2006,  12:05 Найти цитируемый пост)
Потому что char * и char[] это структурно уже не одно и тоже.

объясни плз в чем разница!


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
sergejzr
Дата 27.9.2006, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(Romikgy @  27.9.2006,  11:30 Найти цитируемый пост)
может , но рабочий smile

Рабочий он, но только с одномерным массивом, потому что реализачия действительно на большинстве компилеров почти одинакова.

Цитата(Romikgy @  27.9.2006,  11:30 Найти цитируемый пост)
объясни плз в чем разница! 

На примере многомерного попробую обьяснить.
Как мы знаем, многомерный массив после аллокации и инициализации будет выглядеть так:

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; Такого например уже хороший компилер сделать не даст, но компилер всегда можно обмануть (как ты и сделал).

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



--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Romikgy
Дата 27.9.2006, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



sergejzr, я ниче не понял smile
имхо 
Цитата(sergejzr @  27.9.2006,  12:53 Найти цитируемый пост)
x[i]=randomstring();//предположим, эта функция возвращает char* 

это не правомерно т.к. 
Цитата(sergejzr @  27.9.2006,  12:53 Найти цитируемый пост)
char *x=new char [5];

это дин. массив чаров, а ты туда указатель на чар  smile 
Цитата(sergejzr @  27.9.2006,  12:53 Найти цитируемый пост)
но компилер всегда можно обмануть (как ты и сделал).

имхо я не обманывал , а преобразовал к нужному типу.
Цитата(sergejzr @  27.9.2006,  12:53 Найти цитируемый пост)
при этом если обращаемся к динамическому х х[2][3], то берётся третья буква второго элемента, а если обращаемся к "статическому" y y[2][3], то index элемента в массиве будет вырешан. например 2*5+3;

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


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Romikgy
Дата 27.9.2006, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  27.9.2006,  13:58 Найти цитируемый пост)
указательна массив и массив - разные вещи.

да не спорю 
char s[]
и 
char *s[] 
это разные вещи, но это понять не могу
Цитата(sergejzr @  27.9.2006,  13:58 Найти цитируемый пост)
Один раз у тебя массив элементов char[][] а другой раз массив из указателей на другие массивы char** 

мне не понятна в чем разница между char** и char [][] я имею ввиду для дальнейшего использования , ане для инициализации?


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
sergejzr
Дата 27.9.2006, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Сейчас, разделю темку, а то оффтоп пошёл smile

ПС:
Ну представь, функция у тебя

void test(char**x){}

а ты ей y[][] передал smile


Набросал примерчик. Смотри то, что выделено тире smile

Код

//Это всё необходимо для компиляции. К самому вопросу мало относится 
//Имтересная часть выделена тире
#include <cstdlib>
#include <iostream>

using namespace std;
#define dim1 2
#define dim2 3
char* randomstring(int cnt);

int main(int argc, char *argv[])
{
   //Вот два массива, которые мы и будем сравнивать между собой
    char y[dim1][dim2];
    char **x;
    
//Проинициализируем их одинаковыми значениями
    x=new char *[dim1];
    for(int i=0;i<dim1;i++)
    {
     x[i]=randomstring(dim2);
    }

    for(int i=0;i<dim1;i++)
    {
     for(int z=0;z<dim2;z++)
     y[i][z]=x[i][z];
    }


//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------   
    //Остюда собственно начинается самое интересное...
    for(int i=0;i<dim1;i++)
    {
     for(int z=0;z<dim2;z++)
     printf("x[%i][%i]=%c\t\t y[%i][%i]=%c\n",i,z,x[i][z],i,z,y[i][z]);
     //Как видим значения в обеих массивах совпадают до байта. Операторы доступа также идентичны на первый взгляд, оба - []
     //И хотя нам кажется, что скобки в обоих случаях работают одинакого, это не так
     //Это нам докажет следующий цикл
    }
    
    
    char **tricky; //Это будет вспомогательный указатель

    tricky=(char **)y; //О-о! Тут мы обманываем не только компилятор, но и сами себя, как выяснится вскоре.
    
    for(int i=0;i<dim1;i++)
    {
     for(int z=0;z<dim2;z++)
     printf("tricky[%i][%i]=%c\n",i,z,tricky[i][z]);
     //Здесь прога вылетит со скрипом.
     //Всё дело в том, что оператор[] по разному работает для статических и динамических массивов
    }
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 



//Дальше можно не рассматривать.
return 0;

}
char* randomstring(int cnt)
{
char *ret=new char[cnt];
for(int i=0;i<cnt;i++)
{
        ret[i]='0'+rand()%70;
}
  return ret;    
}


Так что char*,char**, и char[][] это всё разные вещи и преображать одно к другому можно лишь точно понимая, что ты делаешь.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Romikgy
Дата 28.9.2006, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  27.9.2006,  14:15 Найти цитируемый пост)
Сейчас, разделю темку, а то оффтоп пошёл 

вот я ее и посеял smile
Цитата(sergejzr @  27.9.2006,  14:15 Найти цитируемый пост)
tricky=(char **)y; //О-о! Тут мы обманываем не только компилятор, но и сами себя, как выяснится вскоре.
    
    for(int i=0;i<dim1;i++)
    {
     for(int z=0;z<dim2;z++)
     printf("tricky[%i][%i]=%c\n",i,z,tricky[i][z]);
     //Здесь прога вылетит со скрипом.
     //Всё дело в том, что оператор[] по разному работает для статических и динамических массивов
    }

имхо не корректное преобразование т.к. при обращении tricky[i][z] мы должны знать размерность массива , а при передаче tricky=(char **)y; мы по минимуму теряем 1  размерность , и я такого нигде не видел,
везде где идет передача массива более 1 размерности , тогда делают типа такого 
 tricky[][5] тогда понятно будет проге что у нас массив какая то куча строк и 5 столбцов (ну или наоборот)
имхо приобразование как я делал , никакого обмана не несет , а твой пример серьйозно обманывает и компилятор и себя , плюс приводит к неработоспособности проги!


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
MAKCim
Дата 28.9.2006, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

мне не понятна в чем разница между char** и char [][] я имею ввиду для дальнейшего использования , ане для инициализации? 

char** и char[][] - разные типы - в этом вся разница, другое дело, что их использование тесно переплетается


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Romikgy
Дата 28.9.2006, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(MAKCim @  28.9.2006,  12:22 Найти цитируемый пост)
char** и char[][] - разные типы 


MAKCim, давай без пространственных фраз в чем они разные?


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
sergejzr
Дата 28.9.2006, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(Romikgy @  28.9.2006,  10:53 Найти цитируемый пост)
имхо приобразование как я делал , никакого обмана не несет

Ты там по живому режешь и просто везёт, что в данном случае реализация char* и char[] совпали. 
А что если компилятор из char[] вообще свой класс делает у которого оператор[] переложен? Стандарт такое позволяет делать.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
MAKCim
Дата 28.9.2006, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

MAKCim, давай без пространственных фраз в чем они разные? 

что значит в чем?
char** - двойной указатель на char - указывает на указатель, который содержит адрес char
char[][] - тип двумерного массива - нельзя неявно преобразовать к char**
может еще указатель и массив одно и то же?

Это сообщение отредактировал(а) MAKCim - 28.9.2006, 13:41


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Romikgy
Дата 28.9.2006, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  28.9.2006,  12:33 Найти цитируемый пост)
класс делает у которого оператор[] переложен?

не понял smile
Цитата(MAKCim @  28.9.2006,  12:40 Найти цитируемый пост)
еще указатель и массив одно и то же?

объясни в чем разница между массивами и указателями в си?


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
EvgenZ
Дата 28.9.2006, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Freedom in me
**


Профиль
Группа: Участник
Сообщений: 407
Регистрация: 3.8.2006

Репутация: 1
Всего: 11



А я думал, что имя массива и есть указатель... И что кому как удобнее тот так и делает (* или [] )


--------------------
<удалено администрацией форума>
PM MAIL   Вверх
sergejzr
Дата 28.9.2006, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(Romikgy @  28.9.2006,  11:29 Найти цитируемый пост)
давай без пространственных фраз в чем они разные? 

Я же специально во втором посте этой теме это попытался расжевать smile

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 
Цитата(Romikgy @  28.9.2006,  11:46 Найти цитируемый пост)
объясни в чем разница между массивами и указателями в си? 

Массив - структурированный участок памяти. Указатель - ячейка памяти.

Цитата(EvgenZ @  28.9.2006,  11:49 Найти цитируемый пост)
А я думал, что имя массива и есть указатель... И что кому как удобнее тот так и делает (* или [] ) 

Массив никуда "указывать" не может. В отличии от указателя, который как раз на массив может также указывать.


Я не могу больше обьяснять. Просто не знаю как понятнее сказать..

Цитата(Romikgy @  28.9.2006,  11:46 Найти цитируемый пост)
не понял smile

Знаешь такой класс Vector? В нём тоже есть оператор [] и работает как массив, но Vector это КЛАСС и преобразовать его в массив путём обьявления - приведёт к неопределённым последствиям.



--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
EvgenZ
Дата 28.9.2006, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Freedom in me
**


Профиль
Группа: Участник
Сообщений: 407
Регистрация: 3.8.2006

Репутация: 1
Всего: 11



Мне в голову пригшла мысль, т.е. если у меня есть массив [][] , то я могу обращаться к нему с помощью указателей ** , а если он представлен у меня **, то я немогу использовать [][]. Правильно?


--------------------
<удалено администрацией форума>
PM MAIL   Вверх
sergejzr
Дата 28.9.2006, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Это разные вещи и нельзя ни того, ни другого. В примере кода я показал, как из char** правильно сделать char[][] - копированием при инициализации. И как неправильно - преобразованием (char**);


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
MAKCim
Дата 28.9.2006, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

объясни в чем разница между массивами и указателями в си? 

Блин, ну открой K&R и посмотри
Вся фишка в том, что если два понятия можно использовать схожим образом - это еще не значит что это одно и то же
Массив - это последовательность элементов одного типа (располагаются в памяти друг за другом)
Указатель - переменная, содержащая виртуальный адрес какого-то объекта
Касаясь отличий, да возьмем хотя-бы такой пример
Код

#include <stdio.h>

int main()
{
    char array[10], *ptr;
    ptr = NULL;
    array = NULL;  /* Error */
    printf("%d\n%d\n",sizeof(char*),sizeof(array)); /* Почти всегда 4 и 10 */
    return 0;
}

Хотя бы это показывает, что char* и char[] - разные понятия

Добавлено @ 14:10 
Цитата

т.е. если у меня есть массив [][] , то я могу обращаться к нему с помощью указателей ** , а если он представлен у меня **, то я немогу использовать [][]. Правильно?

Первое неправильно, второе правильно
p[i][j] ~ *(*(p+i)+j);
но
char** p = array неправильно синтаксически если array это char[2][2] к примеру, т к разные типы
можно конечно с помощью (char**) или в С++ с помощью reinterpret_cast<char**> привести но зачем?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
SergeCpp
Дата 28.9.2006, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


 
**


Профиль
Группа: Участник
Сообщений: 955
Регистрация: 8.8.2005
Где: At Home

Репутация: 15
Всего: 124



...из книги Сергея Деревяго C++ 3rd: комментарии

Встроенные в C++ типы низкого уровня, такие как указатели и массивы, имеют соответствующие операции, поэтому мы можем записать: 

Код
char vc1[200];
char vc2[500];

void f()
{
 copy(&vc1[0],&vc1[200],&vc2[0]);
}


Ну, если к делу подойти формально, то записать мы так не можем. Вот что говорит об этом д-р Страуструп:

Цитата(Страуструп)
The issue is whether taking the address of one-past-the-last element of an array is conforming C and C++. I could make the example clearly conforming by a simple rewrite: 

    copy(vc1,vc1+200,vc2);

However, I don't want to introduce addition to pointers at this point of the book. It is a surprise to most experienced C and C++ programmers that &vc1[200] isn't completely equivalent to vc1+200. In fact, it was a surprise to the C committee also and I expect it to be fixed in the upcoming revision of the standard. (also resolved for C9x - bs 10/13/98). 

Суть вопроса в том, разрешено ли в C и C++ взятие адреса элемента, следующего за последним элементом массива. Я мог сделать пример очевидно корректным простой заменой: 

    copy(vc1,vc1+200,vc2);

Однако, я не хотел вводить сложение с указателем в этой части книги. Даже для самых опытных программистов на C и C++ большим сюрпризом является тот факт, что &vc1[200] не полностью эквивалентно vc1+200. Фактически, это оказалось неожиданностью и для C комитета, и я ожидаю, что это недоразумение будет устранено в следующих редакциях стандарта.


Так в чем же нарушается эквивалентность? По стандарту C++ мы имеем следующие эквивалентные преобразования: 

&vc1[200] -> &(*((vc1)+(200))) -> &*(vc1+200)

Действительно ли равенство &*(vc1+200) == vc1+200 неверно? 

Цитата(Страуструп)
It is false in C89 and C++, but not in K&R C or C9x. The C89 standard simply said that &*(vc1+200) means dereference vc1+200 (which is an error) and then take the address of the result, and the C++ standard copiled the C89 wording. K&R C and C9x say that &* cancels out so that &*(vc1+200) == vc2+200. 

Это неверно в С89 и C++, но не в K&R C или С9х. Стандарт С89 говорит, что &*(vc1+200) означает разыменование vc1+200 (что является ошибкой) и затем взятие адреса результата. И стандарт C++ просто взял эту формулировку из С89. Однако K&R C и С9х устанавливают, что &* взаимно уничтожаются, т.е. &*(vc1+200) == vc1+200.


Спешу вас успокоить, что на практике в выражении &*(vc1+200) некорректное разыменование *(vc1+200) практически никогда не произойдет, т.к. результатом всего выражения является адрес и ни один серьезный компилятор не станет выбирать значение по некоторому адресу (операция разыменования) чтобы потом получить тот же самый адрес с помощью операции &. 

PM MAIL WWW ICQ   Вверх
likehood
Дата 28.9.2006, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


Профиль
Группа: Участник
Сообщений: 536
Регистрация: 21.12.2005

Репутация: 8
Всего: 24



Цитата(MAKCim @  28.9.2006,  15:04 Найти цитируемый пост)
Хотя бы это показывает, что char* и char[] - разные понятия

В качестве параметра функции это одно и то же.
PM MAIL   Вверх
sergejzr
Дата 28.9.2006, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(baronp @  28.9.2006,  12:33 Найти цитируемый пост)
В качестве параметра функции это одно и то же. 

т.е

int y(char[]) это то же, что и int x(char*) ? (я уже про многомерные не говорю)

при вызове y массив скопируется в стек полностью, при вызове x скопируется только указатель на него.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Romikgy
Дата 28.9.2006, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Код

int y(char x[])
{
  cout<<x;
}
int y1(char*x)
{
  cout<<x;
}
int main(int argc, char* argv[])
{
        char sx[20];
        memset(sx,0,20);
        sprintf (sx,"Privet");
        y(sx);
        printf("\n");
        y1(sx);
        printf("\n");
        system("PAUSE");
        return 0;
}

Код

00401598 6A00             push 0x00
0040159A 8D45EC           lea eax,[ebp-0x14]
0040159D 50               push eax
0040159E E8A9030000       call CC3260MT._memset
004015A3 83C40C           add esp,0x0c
Unit1.cpp.23: sprintf (sx,"Privet");
004015A6 68A4204000       push 0x004020a4
004015AB 8D55EC           lea edx,[ebp-0x14]
004015AE 52               push edx
004015AF E8A4030000       call CC3260MT._sprintf
004015B4 83C408           add esp,0x08
Unit1.cpp.24: y(sx);
004015B7 8D4DEC           lea ecx,[ebp-0x14]
004015BA 51               push ecx
004015BB E8A8FBFFFF       call y(char *)
004015C0 59               pop ecx
Unit1.cpp.25: printf("\n");
004015C1 68AB204000       push 0x004020ab
004015C6 E887030000       call CC3260MT._printf
004015CB 59               pop ecx
Unit1.cpp.26: y1(sx);
004015CC 8D45EC           lea eax,[ebp-0x14]
004015CF 50               push eax
004015D0 E8A3FFFFFF       call y1(char *)
004015D5 59               pop ecx
Unit1.cpp.27: printf("\n");
004015D6 68AD204000       push 0x004020ad
004015DB E872030000       call CC3260MT._printf
004015E0 59               pop ecx
Unit1.cpp.28: system("PAUSE");
004015E1 68AF204000       push 0x004020af
004015E6 E879030000       call CC3260MT._system
004015EB 59               pop ecx
Unit1.cpp.29: return 0;
004015EC 33C0             xor eax,eax
Unit1.cpp.30: }
004015EE 8BE5             mov esp,ebp
004015F0 5D               pop ebp

еще вопросы smile

Добавлено @ 15:24 
Цитата(MAKCim @  28.9.2006,  13:04 Найти цитируемый пост)
Хотя бы это показывает, что char* и char[] - разные понятия

Давайте народ определимся о каких вещах мы говорим, об объявлении переменых , или об передаче переменых в ф_цию?


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
sergejzr
Дата 28.9.2006, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Перестаньте приводить ассемблерские кода. Это не доказательство никакое!!!
 Они разные получаются в зависимости от оптимизатора и конкретного компилера. Если у задачи существует оптимальное решение и оптимизатор его знает, то он любой код, приводящий это решение, скомпилит в одинаковый машинный код. Это не значит, что измени условие задачи, вывод останется тем же.!!
Цитата(Romikgy @  28.9.2006,  13:22 Найти цитируемый пост)
Код

char sx[20];
        memset(sx,0,20);

Зачем там memset, если место ты уже [] выделил?






--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
MAKCim
Дата 28.9.2006, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

Давайте народ определимся о каких вещах мы говорим, об объявлении переменых , или об передаче переменых в ф_цию? 

В любом случае char* - char[], так же как и char** - char[][] - разные понятия
При вызове функции в стек копируется адрес первого элемента массива
Т. е компилятор сам осуществляет преобразование, массива в адрес первого элемента, создавая впечатление эквивалентности этих понятий (указателя и массива). Но они не эквивалентны как не крути - массив - это массив, переменная - это переменная!

Добавлено @ 15:32 
Цитата

Зачем там memset, если место ты уже [] выделил?

В стеке переменные по-умолчанию не инициализируются 0
Цитата

Перестаньте приводить ассемблерские кода. Это не доказательство никакое!!!
 Они разные получаются в зависимости от оптимизатора и конкретного компилера. Если у задачи существует оптимальное решение и оптимизатор его знает, то он любой код, приводящий это решение, скомпилит в одинаковый машинный код. Это не значит, что измени условие задачи, вывод останется тем же.!!

Здесь я бы не спорил, т. к
если в сигнатуре функции мы пишем int a[20]/[], то передается все равно указатель 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
sergejzr
Дата 28.9.2006, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(MAKCim @  28.9.2006,  13:30 Найти цитируемый пост)
В стеке переменные по-умолчанию не инициализируются 0

А зачем так писать, если не инициализируешь?
написал бы второй строкой sx[0]='s'.
Выделять память там полюбому не надо.



--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Romikgy
Дата 28.9.2006, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  28.9.2006,  14:29 Найти цитируемый пост)
Зачем там memset, если место ты уже [] выделил?

мемсет у мя обнуляет выделеную память smile

Добавлено @ 15:49 
Цитата(sergejzr @  28.9.2006,  14:45 Найти цитируемый пост)
Выделять память там полюбому не надо.

а куда тогда писать? мы выделяем память или в хипе динамически, или в стеке если массивом


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
sergejzr
Дата 28.9.2006, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(Romikgy @  28.9.2006,  13:45 Найти цитируемый пост)
мемсет у мя обнуляет выделеную память smile 

Зачем? Но это к делу отношения не имеет..

Естесственно компилер любой код приведёт к указателям и числам. Как и классы ООП, массивы являются лишь обёрткой следующего уровня.

Добавлено @ 15:52 
чар[20] - ты уже этим память выделил. Туда и писать.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Romikgy
Дата 28.9.2006, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  28.9.2006,  14:51 Найти цитируемый пост)
чар[20] - ты уже этим память выделил. Туда и писать. 

да но посмотри что в этих чарах лежит сразу после выделения smile
Цитата(sergejzr @  28.9.2006,  14:51 Найти цитируемый пост)
Естесственно компилер любой код приведёт к указателям и числам.

дык а кто юзает код проги , компиляторы smile


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
sergejzr
Дата 28.9.2006, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(Romikgy @  28.9.2006,  14:01 Найти цитируемый пост)
да но посмотри что в этих чарах лежит сразу после выделения

Какайя разница, что там лежит? Мусор какой нибудь.

Добавлено @ 16:11 
Убери мемсет из кода. Ничего не изменится.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
likehood
Дата 28.9.2006, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


Профиль
Группа: Участник
Сообщений: 536
Регистрация: 21.12.2005

Репутация: 8
Всего: 24



Цитата(sergejzr @  28.9.2006,  15:40 Найти цитируемый пост)
int y(char[]) это то же, что и int x(char*) ?

да
Цитата(sergejzr @  28.9.2006,  15:40 Найти цитируемый пост)
(я уже про многомерные не говорю)

а я про них тоже не говорил  smile 

Цитата(sergejzr @  28.9.2006,  15:40 Найти цитируемый пост)
при вызове y массив скопируется в стек полностью

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

Цитата(MAKCim @  28.9.2006,  16:30 Найти цитируемый пост)
Т. е компилятор сам осуществляет преобразование, массива в адрес первого элемента, создавая впечатление эквивалентности этих понятий (указателя и массива).

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

p.s. с многомерными массивами все не так просто
PM MAIL   Вверх
Romikgy
Дата 28.9.2006, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  28.9.2006,  15:11 Найти цитируемый пост)
Убери мемсет из кода. Ничего не изменится.

согласен , но имхо лучше когда обнуляешь


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
MAKCim
Дата 28.9.2006, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата

все таки массив - это структура данных в памяти, она никуда не преобразовывается.

я немного не так выразился


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
sergejzr
Дата 28.9.2006, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: 19
Всего: 360



Цитата(Romikgy @  28.9.2006,  14:42 Найти цитируемый пост)
согласен , но имхо лучше когда обнуляешь 

Чем?


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
likehood
Дата 28.9.2006, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


Профиль
Группа: Участник
Сообщений: 536
Регистрация: 21.12.2005

Репутация: 8
Всего: 24



если что-то нехорошее может произойти, оно обязательно произойдет.
поэтому иногда лучше перестраховаться (хотя в данном случае и не обязательно).
PM MAIL   Вверх
EvgenZ
Дата 28.9.2006, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Freedom in me
**


Профиль
Группа: Участник
Сообщений: 407
Регистрация: 3.8.2006

Репутация: 1
Всего: 11



baronp, прав массив передается в функцию как указатель.


--------------------
<удалено администрацией форума>
PM MAIL   Вверх
Romikgy
Дата 29.9.2006, 08:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(sergejzr @  28.9.2006,  16:04 Найти цитируемый пост)
Чем?

мемсетом smile 


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
UnrealMan
Дата 29.9.2006, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(sergejzr @  28.9.2006,  14:40 Найти цитируемый пост)
т.е

int y(char[]) это то же, что и int x(char*) ? 

char[] – это не тип, а обозначение. Для аргумента функции оно означает абсолютно то же самое, что и char *. Типом же является char[n], где n – некоторая константа.

Цитата(baronp @  28.9.2006,  16:37 Найти цитируемый пост)
все таки массив - это структура данных в памяти, она никуда не преобразовывается

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

Цитата(baronp @  28.9.2006,  16:37 Найти цитируемый пост)
Просто когда мы передаем массив в функцию всегда передается его адрес, сама же функция не может определить чем был исходный массив: обычным статическим масивом или указателем, ссылающимся на динамич. массив. В этом смысле при передаче одномерного массива разницы между массивами и указателями нет.

Это ты рассказываешь про функции, аргументы которых объявлены как указатели. Было бы странно ожидать от них чего-то другого.

Для того, чтобы передать в функцию массив (а не просто указатель на его первый элемент) используется ссылка на массив:

Код
int array[10];
void Func(int (&arr)[10]);

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

Если требуется передать массив произвольного размера, то можно воспользоваться шаблоном:

Код
int array1[10];
int array2[20];

template <size_t size>
void Func(int (&arr)[size]);


Так что шаблонная функция вполне может определить, чем был исходный массив.

Цитата(Romikgy @  29.9.2006,  08:50 Найти цитируемый пост)
мемсетом

А списком инициализации не судьба?

Код
char array[20] = {};


Это сообщение отредактировал(а) UnrealMan - 1.10.2006, 20:37
PM MAIL   Вверх
Romikgy
Дата 29.9.2006, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 8
Всего: 146



Цитата(UnrealMan @  29.9.2006,  08:44 Найти цитируемый пост)
char array[20] = {0};

прикольно не знал smile 


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
UnrealMan
Дата 29.9.2006, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 27
Всего: 32



Цитата(Romikgy @  29.9.2006,  09:59 Найти цитируемый пост)
прикольно не знал 

Если массив будет полем класса, то такой подход не пройдёт. Но даже в этом случае прямое применение memset – не лучшее решение. Надёжнее будет написать коротенькую функцию-шаблон для обнуления:

Код
template <class T, size_t size>
ZeroArray(T (&arr)[size])
{
    memset(arr, 0, size*sizeof(T));
}

Теперь не нужно указывать точный размер массива (функция сама его выведет).
PM MAIL   Вверх
Athlon
Дата 29.9.2006, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 15.1.2006
Где: Украина:: Запорож ье

Репутация: нет
Всего: нет



Когда я начинал читать эту тему, то думал, что четко представляю себе различие между передачей параметров по ссылке(char*) и по значению(char[]), а теперь выяснил, что в обоих случаях происходит передача по ссылке и если я изменю значения массива переданого функции, то эти изменения останутся после выхода из функции, например так:
Код

void some_func(char array[])
{
    //............
    array[0] = '1';
    //............
}

void main()
{
    char ch[20];
    ch[0] = '2';
    some_func(ch);
    cout<<ch[0];
}

Т.е. на выходе я получу '1', есть ли еще где-то такие фишки(параметр переданый по значению передается по ссылке)
P.S. это конечно отвратительный стиль менять объекты переданные по значению, но мне любопытно узнать есть ли еще такие фокусы

Это сообщение отредактировал(а) Athlon - 29.9.2006, 15:52
PM MAIL ICQ   Вверх
Oleg_Ci
Дата 15.10.2006, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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 !
Вобщем так получается:
Цитата(sergejzr @  28.9.2006,  17:50 Найти цитируемый пост)
содержимое указателей на указатели может частями находится в любом месте RAM.А у char[10][10] всего 50 байт и все лежат массивом подряд.
Код

#include<iostream>
#include<stdlib.h>
using std::cout;
using std::endl;

int main(int argc, char* argv[])
{    
    const int len = 10; // длинна массива, можно поэксперементировать с ней
    char a[len][len]; // обычный массив

    char **b; // указатели на указатели
    b = new char*[len];
    for ( int i=0; i<len; i++ )
        b[i] = new char[len];

    for ( int i=0; i<len; i++ ) // записываем в массивы буквы
        for ( int j=0; j<len; j++ )
            if ( j==len-1 ) a[i][j] = b[i][j] = 0; // конец строки
            else a[i][j] = b[i][j] = 'a' +j + i; // символы 'a', 'b', ...

/* здесь выводим адреса начала строк в обычном массиве
 и сами строки    */
    for ( int i=0; i<len; i++ )
        cout << (int)&a[i][0] << " -> " << a[i] <<endl;
//_________________________________________
//////// собственно самое итересное здесь начинается /////////////

// тэст обычтого массива:
// 1) выводим расстояние между первой и второй строками (количество байт)
    cout << "\nLength str2 - str1 = " << (int) &a[1][0] - (int) &a[0][0] << "\n";
// 2) выводим то куда указывает указатель начала первой строки
// плюс длинна(len) этой самой строки
    cout << "char a[][] + " << len << " -> " <<(char*) &a[0] +len << "\n";
// 3) выводим занимаемую всем массивом память (нумерация с нуля)
// самое гланое наверно:
    cout << "Size matrix = " 
    << (int) &a[len-1][len-1] - (int) &a[0][0] <<  "  !!!!!\n\n";

/* здесь выводим адреса начала строки в указателях на указатели
 и сами строки    */
    for ( int i=0; i<len; i++ )
        cout << (int)&b[i][0] << " -> " << b[i] <<endl;

/////////// собственно самое итересное здесь /////////////////
// тэст указателей на указатели
    cout << "\nLength str2 - str1 " << (int) &b[1][0] - (int) &b[0][0] << "\n";
    cout << "char **a + " << len << " -> " <<(char*) &b[0] +len << "\n";
    cout << "Size matrix = "
    << (int) &b[len-1][len-1] - (int) &b[0][0] << "  !!!!!\n\n";

// удаляем память
    for ( int j=0; j<10; j++ )
        delete [] b[j];
    delete [] b;

    system("pause");
    return 0;
};

PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1503 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.