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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разница между [] и * 
:(
    Опции темы
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   Вверх
Страницы: (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.0752 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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