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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многомерные массивы и указатели, Как получить адрес элемента массива 
V
    Опции темы
JackYF
Дата 30.4.2007, 05:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Я утверждаю, что двухмерные массивы С++ приводятся к двойному указателю согласно правилам стандарта.


Попробую оспорить эту фразу таким кодом:

Код

void my_func(const int** p, int m, int n)
{
  for ( int i = 0; i < m; ++i )
  {
    cout << p[i][j];
  }
}

int main()
{
  //--------------------------
  // 1
  //--------------------------
  int a[2][3];
  // инициализация...
  my_func( a, 2, 3 );

  //------------------------------
  // 2
  //------------------------------
  int** b = new int*[2];
  for ( int i = 0; i < 2; ++i )
  {
    b[i] = new int[3];
  }
  // инициализация
  my_func( b, 2, 3);
}


Если двумерные массива приводятся к двойному указателю, то объясни, почему не компилируется часть 1 моего примера.
И почему, если даже сделать reinterpret_cast<int**>, то функция будет работать неверно?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Fazil6
Дата 30.4.2007, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

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



Цитата(Anikmar @  29.4.2007,  23:52 Найти цитируемый пост)
Преобразование стандартное, все в порядке, но sizeof(a) и sizeof(aa) также будут отличаться. Однако это ведь вас не смущает? Тем не менее a ведет себя как указатель на int, тогда согласно вашей логике это не так - так как sizeof дают разные результаты?

Что дает разные результаты? при чем здесь sizeof(a) и sizeof(aa) ??? 
Вы Вместо того чтобы с пеной у рта доказывать что я дурак подумали бы оба что вы пишете и внимательно почитали что я пишу.

int a[5]; - а как указатель на int -> в вычислениях указателя a + sizeof(int)

int *aa - > в вычислениях aa + sizeof(int)

где здесь будет тличие и разный результат????

Цитата(Anikmar @  29.4.2007,  23:52 Найти цитируемый пост)
Я не говорю, что имя двухмерного массива является двойным указателем. Можно сказать, что это производный тип двойного указателя с перегруженной арифметикой. Однако если работать с ним как с двойным указателем он выдает именно тот результат, который ожидается.
Это твои фантазии особенно про перегрузку

Цитата(Anikmar @  29.4.2007,  23:52 Найти цитируемый пост)
Если вам будет легче, то int** является базовым типом для массива. Массив это частный случай поведения, в том числе и рассчета указателя. Еще раз повторю, в связи с тем что массив не является int**, но должен вести себя как int  арифметика в нем естественно работает по-другому.

фантазии....

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


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



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

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

Цитата(JackYF @  30.4.2007,  05:01 Найти цитируемый пост)
Цитата(Anikmar @  29.4.2007,  11:08 )
Я утверждаю, что двухмерные массивы С++ приводятся к двойному указателю согласно правилам стандарта.
Попробую оспорить эту фразу таким кодом:


Тут немного не так звучит моя фраза. Весь наш спор был об использовании имени массива. Не передачи его в функцию. В рамках функции это уже чисто двойной указатель и функция с ним работает уже по правилам двойного указателя (т.е. с базовым классом) и ничего не знает о статическом массиве (производном классе). 

Если мы хотим сделать функцию, куда мы можем передать как статический массив переменного размера так и динамический - без дополнительной работы не выйдет.
Что предлагает Страуструп. Он предлагает преобразовывать статический двухмерный  массив в одномерный, передавать в функцию его базовый адрес и размерности, а смещение элемента вычислять динамически по мере надобности. Достаточно странная рекомендация человека, разработавшего этот язык. Если матрица достаточно большая, а элементы нужны не по порядку а вразброс - то это будет накладка по времени и причем серьезная. И внутри функции этот массив уже даже не выглядит массивом - так как нельзя использовать операции извлечения элемента по индексу. Для меня это полная загадка - сделали бы инициализированный массив указателей как сами же написали в стандарте и все было бы замечательно (правда кроме этого спора - его не было бы). Вместо этого этой теме мало того, что посвящают достаточно большую главу в стандарте, еще и в книгах кто как горазд пишет. И ведь действительно, идиотская ситуация: один и тот же логический объект (двухмерный массив) по-разному храниться при статическом и при динамическом варианте создания. По меньшей мере странно. 

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

Ну это все вода. К сожалению по сути вашего вопроса говорю, что имя двухмерного массива можно использовать как двойной указатель только в рамках блока, в котором он определен. Дальше уже хлопоты - хотите делать функцию, которая работает и со статическими массивами и с динамическими - без накладных расходов не выйдет. Так уж устроен язык. Либо теряем возможность удобной работы через квадратные скобки, либо перед передачей статического массива приводим его полностью через промежуточный массив указателей к двойному указателю.
Можно конечно и наоборот сказать, что это двойной указатель ведет себя как статический массив. Но вот тут как раз и есть костяк моего мнения: для того, чтобы сделать работу хотя бы в рамках блока универсальной и перегружена указательная арифметика статического массива. Для чего так было наворачивать я не знаю - было бы все одинаково было бы проще.

Всяк жизнь прграммисту наровит испротить  smile 


Это сообщение отредактировал(а) Anikmar - 30.4.2007, 09:45
PM MAIL ICQ   Вверх
MAKCim
Дата 30.4.2007, 09:54 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



<type> a[N] - массив размерности 1 - есть суть последовательность элементов одного типа
<type> a[N][N] - массив размерности 2 - есть суть последовательность массивов размерности 1 элементов одного типа
<type> *a - указатель на элемент определенного типа - есть суть адрес элемента
<type> **a - указатель на указатель элемента определенного типа - есть суть адрес элемента, содержащего адрес элемента
<type> **a != <type> a[N][N] потому как
<type> a[N][N] = {a11, a12,  a13, ... ,a1N, a21, ..., a2N, ..., aN1, ..., aNN}
если <type> **a содержит адрес элемента <type>* и, предположем, этот элемент первый элемент массива из N элементов <type>*, то <type> **a = <type> *a[N] = {a1*, a2*, ..., aN*}, из этого случая видно, что <type> a[N][N] != <type> **a, но т. к арифметика указателей гласит, что, <N раз *>a = a[0]...[0] (N раз), то получаем, что любой массив вида <type> a[A][B][C]... может быть представлен как int<A * B * C * ... раз *>, обратное (как уже показали) не верно

Это сообщение отредактировал(а) MAKCim - 30.4.2007, 09:56


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

PM MAIL   Вверх
Anikmar
Дата 30.4.2007, 12:07 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



У меня сложилось впечатление, что я всем доказываю, что двухмерный массив является двойным указателем, а со мной спорят. Причем иногда мне самому уже так кажется (что я это доказываю) smile.  Я посмотрел последние ответы - они перелезли с темы спора в дебри стандарта и что чем является, в общем становится скучновато и бессмыслено.

Итак подвожу итого:

Все участники спора прекрасно понимают как организованы в памяти массивы как статические так и динамические. Это на самом деле главное - никто не наворотит ошибок, связанных с непониманием вопроса.
Пролистал ответы  и что-то не увидел внятного  примера передачи любого массива в функцию - сразу какой-то спор пошел, а тема именно с этого началась.  smile Вроде изначально об этом спрашивали, потом был длинный спор с DOVом (ИМХО некоторые опоненты достаточно резко себя вели (причем неоправдано), и в общем то пример DOVa был работоспособен - я честно говоря не понял, почему там развернулась вторая волна спора, но в том споре я не учавствовал, хотя ИМХО Dov был прав).

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

Исходя из этого, я подведу итого - так как окончательно точку в споре может поставить только самый свежий стандарт C++, его я не нашел, нашел только теоретические статьи, где про нашу тему скромно говориться "вопрос в стадии решения". Может где-то что-то и есть - просто я не нашел.

Итак ИТОГО, что я собрал из всей темы:

1. Имя двухмерного статического массива двойным указателем не является.

2. Для передачи статически объявленного массива в функцию объявление такого массива в основной программе и в функции должно совпадать. Т.е. статический массив переменной размерности в функцию без дополнительных ухищрений и приведения типа не передать. По сути это означает, что в языке нет типа "двухмерный массив" - так как универсальное описание двухмерного массива переменного размера отсутствует. Это же относится к оличеству измерений больше 2.

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

4. Двойной указатель можно представить при надлежащей инициализации двухмерным массивом. 

5. Физическая организация многомерного массива при статическом объвлении и динамическом создании отличается как минимум на дополнительный массив указателей для каждого измерения свыше 1.

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

Еще раз всем спасибо.  smile 
PM MAIL ICQ   Вверх
Fazil6
Дата 30.4.2007, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

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



Цитата(Anikmar @  30.4.2007,  09:44 Найти цитируемый пост)
Тут немного не так звучит моя фраза. Весь наш спор был об использовании имени массива. Не передачи его в функцию. В рамках функции это уже чисто двойной указатель и функция с ним работает уже по правилам двойного указателя (т.е. с базовым классом) и ничего не знает о статическом массиве (производном классе). 


Цитата(Anikmar @  30.4.2007,  09:44 Найти цитируемый пост)
 К сожалению по сути вашего вопроса говорю, что имя двухмерного массива можно использовать как двойной указатель только в рамках блока, в котором он определен.

ты сам себе противоречишь. В месте вызова функции массив определен и размерности его известны. То что будет дальше (внутри функции) нас вообще не интересует потому что такой код все равно не компилится. Значит нельзя использовать имя масива как двойной указатель. 

Ты утверждаешь, что если по стандарту имя  int а[2] может использоваться как int* , то продолжая эту аналогию int aa[2][2] можно использовать как int**. У нас (несогласных с этой точкой зрения и считающих, что это заблуждение и необоснованые домыслы) возникает справедливый вопрос : почему тогда это не переносится на примеры кода?
Код

int a[2];
int aa[2][2];

int *pa = a; // компилируется
int **paa = a; // а это не компилируется. Причем компилятор четко говорит что типы несовместимы


Цитата(Anikmar @  30.4.2007,  09:44 Найти цитируемый пост)
 Но вот тут как раз и есть костяк моего мнения: для того, чтобы сделать работу хотя бы в рамках блока универсальной и перегружена указательная арифметика статического массива. Для чего так было наворачивать я не знаю - было бы все одинаково было бы проще.
Ничего не перегружено... Все работает как любой другой обычный указатель. Просто не нужно исходить из посыла, что имя двумерного массива двойной указатель. 

По поводу стандарта.
Нет НИГДЕ в стандарте упоминаний того, что имя двумерного массива двойной указатель.  Есть пункт 8.3.4.8, который здесь приводили. Есть еще 8.3.4.7
Цитата

A consistent rule is followed for multidimensional arrays. If E is an n-dimensional array of rank i× j×. . .×k, then
E appearing in an expression is converted to a pointer to an (n−1)-dimensional array with rank j×. . .×k. If the *
operator, either explicitly or implicitly as a result of subscripting, is applied to this pointer, the result is the pointed-to
(n−1)-dimensional array, which itself is immediately converted into a pointer.

сказано совершенно четко, что имя многомерного массива конвертируется в указатель на массив меньшей размерности. Все! Больше никаких конвертаци дальше нет! Сказано, что если к нему применить *operator , то результат этой операции конвертируется тоже в указатель. Для того чтобы получить этот результат (к примеру для двумерного массива) имя массива используется как уазатель на массив, а не на int*. Т.е. уже все, он уже использовался не просто как указатель , а именно как указатель на массив и дальше разглогольствовать, что дескать там тоже конвертируется в указатель не имеет смысла потому, что к имени двумерного массива это уже отношения не имеет.

Цитата(Anikmar @  30.4.2007,  12:07 Найти цитируемый пост)
хотя ИМХО Dov был прав

вчем прав? если
Цитата(Anikmar @  30.4.2007,  12:07 Найти цитируемый пост)
1. Имя двухмерного статического массива двойным указателем не является.


Добавлено через 5 минут и 5 секунд
Цитата(Anikmar @  30.4.2007,  12:07 Найти цитируемый пост)
Я влез в спор по другому поводу именно с примером - как можно имя двухмерного массива использовать как будто это был бы двойной указатель.

ох... неправда... я сразу тебе сказал, что это выглядит только так и поэтому меня не устроило...
Ладно... Закончили и забыли
PS
но Dov неправ
PM MAIL   Вверх
apook
Дата 30.4.2007, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

и в общем то пример DOVa был работоспособен - я честно говоря не понял, почему там развернулась вторая волна спора, но в том споре я не учавствовал, хотя ИМХО Dov был прав


Код

int a[ 3 ][ 3 ] = { {1, 2, 3}, {5, 6, 7}, {8, 9, 10} };

int *pa[ 3 ]={ (int*)a, a[1], a[2] };

пошагам
Код

int *pa[ 3 ];

что такое pa[ 0 ], pa[ 1 ], pa[ 2 ]-

  - это указатели которым надо присвоить адреса(т.к pa это массив из 3-х указателей )

напрашивается
Код

pa[ 0 ]=a[ 0 ]; //или =&a[ 0 ] или =a
...

т.е напрямую или косвенно имеется ввиду значок &

теперь
Код

pa[ 0 ]=(int *)a;
...

абсолютно ненужный (int *)

* и & означают ведь разные вещи

не пример конечно работает..

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



--------------------
Мои руки из дуба, голова из свинца ну и пусть ...
PM MAIL   Вверх
Anikmar
Дата 30.4.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

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



ЭТО МОЙ ПОСЛЕДНИЙ ПОСТ В ЭТОЙ ТЕМЕ - иначе мы ее на завершим.

Цитата(apook @  30.4.2007,  15:41 Найти цитируемый пост)
теперь


pa[ 0 ]=(int *)a;
...


абсолютно ненужный (int *)


Вот как советует приводить первый элемент двойного массива господин Страуструп:

Цитата

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

       int* v = (int*)m;


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

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

ИМХО Код Страуструпа сомнителен с точки зрения быстродействия. 



Цитата(Fazil6 @  30.4.2007,  14:14 Найти цитируемый пост)
ох... неправда... я сразу тебе сказал, что это выглядит только так и поэтому меня не устроило...

Ну не устроило - так не устроило, что я могу сказать. Автора темы - пусть галочку поставит "ТЕМА ЗАКРЫТА"

Хоть как тут  меня называйте и обзывайте - в этой теме больше нислова не скажу  smile 

Это сообщение отредактировал(а) Anikmar - 30.4.2007, 16:07
PM MAIL ICQ   Вверх
Ln78
Дата 30.4.2007, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



FiMa1 и все желающие – получите обещанное окончание. Там есть обращение и к apook. Likehood, threef – основное содержание вам вряд ли будет интересно, но последние 2 страницы, возможно, вам понравятся.  
Fazil6. У меня недостаточно постов, чтобы поставить тебе +, поэтому скажу здесь - молодец. 10 раз объяснять одно и то же, когда и первое объяснение было простым и понятным, сохраняя при этом вежливость и видимое спокойствие, - я бы, наверное, так не смог. Хотя и у тебя уже динамические массивы начали нервно курить. 
В одном из соседних топиков обсуждался, в частности, вопрос выхода из вложенных циклов. Не знаю, какой вложенности здешний «цикл» обсуждений, но это – моя 4-я попытка вставить break. Хотел было обратиться к многоуважаемой Earnest с просьбой поставить здесь свой весомый return, да прочитал абзац про ничего не понимающего в массивах Страуструпа и передумал. Да… В общем, береги невры Fazil6, ты нам нужен живым и здоровым smile .


Присоединённый файл ( Кол-во скачиваний: 11 )
Присоединённый файл  Comment2.rar 29,33 Kb
PM MAIL   Вверх
JackYF
Дата 1.5.2007, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Подведу и я свой мини-итог.

Тип "двойного массива" != тип "двойной указатель".
Внутренности двойного массива не тождественны внутренностям двойного указателя.
Ни неявное, ни явное преобразования не приводят один тип к другому.

То, что объединяет эти два типа - возможность обращения к элементу через двойную индексацию.

Надеюсь, от меня в этой теме тоже все.



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
zkv
Дата 2.5.2007, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Участник Клуба
Сообщений: 2133
Регистрация: 23.7.2006
Где: Санкт-Петербург

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



 smile 
Fazil6, apook, Anikmar, JackYF, 
что это вы на 13-й странице остановились? Примета плохая, надо еще одну-другую накатать smile
PM MAIL   Вверх
FiMa1
Дата 3.5.2007, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Ln78 @ 30.4.2007,  18:04)
FiMa1 и все желающие – получите обещанное окончание.

Ln78, спасибо тебе огромное! Старался читать с особым пристрастием. Есть вопросы...
Цитата
Код
int arA[10];

Обратим внимание, что первая из написанных нами строчек содержит два имени переменных - arA, arA[0]. Нет отдельной сущности, arA, где-то хранящейся. С другой стороны, это – переменная, а для переменной можно использовать операцию взятия адреса. И что здесь делать компилятору? Он говорит про себя «Ужо тебе, озорник»,  но что-то делать всё-таки надо. Вот и присваивает pA[2] то же значение, что и первым двум указателям.

Ну с arA[0], допустим, понятно. Это имя переменной, значением которой м.б. только целое число. arA, насколько я понял - имя указателя, т.е, по-сути, тойже переменной, значением которой, однако, может быть только адрес (ну и другие, в данном контексте несущественные, отличия обычной переменной от указателя). Далее выполняем следующие действия:
Код
int *pArr1 = (int*)&arA;
pArr = arA;

Действия в обоих строках абсолютно одинаковые? Если да, то вопрос2 - как таки работает приведение, использованное в первой строке?
Фактически берем адрес указателя arA, приводим его к указателю.. ну не понятно..
В противном случае, если arA - не указатель, а просто переменная, то почему нельзя записать:
Код
int *pArr = &arA;//error: 'initializing' : cannot convert from 'int (*__w64 )[10]' to 'int *'

Ну и в догонку - что за тип такой 'int (*__w64 )[10]' ?

ДРУЗЬЯ, БОЛЬШАЯ БРОСЬБА В ДАННОМ ТОПИКЕ ДИСКУССИЙ НЕ РАЗВОДИТЬ! РЕЖИМ ВОПРОС-ОТВЕТ ЛИБО РИДОНЛИ ;) СПАСИБО!

Это сообщение отредактировал(а) FiMa1 - 3.5.2007, 14:42
PM   Вверх
Ln78
Дата 3.5.2007, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



FiMa1, как бы тебе ответить, чтобы не спугнуть здешнее затишье? Может, если у тебя ко мне появятся по этой теме ещё вопросы, лучше задавать их в личку? Хотя я на форуме новичок, не знаю, как лучше. 
Собственно, ответ на вопрос. 
Тебе можно считать, что 'int (*__w64 )[10]’  это есть адрес массива из 10 элементов, т.е. собственно то, что написано буквально. Модификатор __w64 это специфическое для VS определение, связанное с вопросами портирования из 32-х в 64-х разрядный компилятор, для тебя, наверное, это неважно. Если  его убрать, то получим просто указатель на массив из 10 элементов. Т.е. если мы напишем так:
      typedef int ArrayInt10[10];
      ArrayInt10 *pAr = &arA;
то никаких замечаний от компилятора, естественно, не получим. Как я там писал, единственная причина, зачем  я написал эту строчку, показав, что и такое сработает: Только для того, чтобы продемонстрировать один нюанс: не следует считать, что для компилятора arA и &arA[0] абсолютно одно и то же. 
Т.е. здесь к arA мы можем применить операцию взятия адреса, а к &arA[0] – нет. Основное, что ты должен запомнить, когда делаешь явные приведения: существует только память под 10 элементов int, к этой памяти можно адресоваться. И на все три варианта будет получен только один ответ: адрес начального элемента массива. Ничего больше нет. Компилятор не выдумщик, ему просто нечего больше возвращать. Все примеры преобразований, которые я приводил, например, с «превращением» двумерного массива в трёхмерный, рисуя таблички, как оно находится в памяти, я приводил для демонстрации этого факта (ни один бит при этих преобразованиях даже не пошевелился, это просто указание компилятору воспринимать область памяти так или иначе). В примере с тем одномерным массивом: есть массив из 10 чисел. Адрес первого (нулевого) элемента этого массива мы в начале привели чёрт знает к чему (могли привезти к указателю на рыжую корову, это сути не меняет), а потом явно сказали, что это всё-таки указатель на целое число (или несколько чисел), т.е. к тому, как оно есть на самом деле. Ещё раз повторюсь, так как написано в первой строке – никогда не делай. 
«Просто переменная» может быть чем угодно и указателем, и указателем на указатель, да мало ли ещё чем. Но при присваивании типы операндов должны совпадать (или для них в языке должны быть определены правила преобразования), иначе компилятор выдаст ошибку. Силой компилятор можно заставить считать, что это другой тип, но дальнейшая ответственность на том, кто такое приведение написал. 

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


Опытный
**


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

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



Цитата(Ln78 @ 3.5.2007,  14:27)
Адрес первого (нулевого) элемента этого массива мы в начале привели чёрт знает к чему (могли привезти к указателю на рыжую корову, это сути не меняет), а потом явно сказали, что это всё-таки указатель на целое число (или несколько чисел), т.е. к тому, как оно есть на самом деле.

Под "привели чёрт знает к чему" ты подразумеваешь то, что мы зачем-то взяли адрес указателя? В то время, как могли бы просто написать int *pArr = (int *)arr; или и подавно int *pArr = arr; вместо:
Код
typedef double Tredcow

int main()
{
    int arr[10] = { 0,1,2 };
    int *pArr = (int *)(Tredcow *)(Tredcow *)&arr;

    return 0;
}

PS: Ln78, не серчай, если шибко надоедаю, заглядывай периодически в топик, вопросы, имхо, будут...

Это сообщение отредактировал(а) FiMa1 - 3.5.2007, 15:04
PM   Вверх
Ln78
Дата 3.5.2007, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



FiMa1, я совсем "не серчаю", что ты. Мы все не экспертами родились, вопросы задавать нормально. "Черт знает к чему" - не от "серчания", а просто, чтобы было понятнее. Я просто боюсь опять поднять волну в этом многострадальном топике. Именно это я и имел в виду. Единственное, всё-таки, нет там указателя (как такового, для которого компилятор отвёл место, для которого можно писать что-то типа int**), есть имя массива, о чём эти 13 страниц и говорили, и примерно столько же я написал тебе в комментариях. 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0662 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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