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

Поиск:

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


Опытный
**


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

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



Привет всем!

Читаю "Программирование на языке Си" Афанасьева, появился вопрос... Автор пишет: "Следующие объявления переменных"
Код

int a[3][3] = { { 11,12,13 },
                    { 21,22,23 },
                    { 31,32,33 }  };

int *pa[3] = { a, a[1], a[2] };
int *p = a[0];

реализуют определенную схему размещения указателей на двумерный массив.
Согласно этой схеме доступ к элементу a[0][0] можно получить по указателям a, p, pa при помощи следующих ссылок: a[0][0], *a, **a[0], *p, **pa, *p[0].
Уже на этапе инициализации массива int *pa[3] = { a, a[1], a[2] }; компилятор генерит error: 'initializing' : cannot convert from 'int [3][3]' to 'int *'.

Помогите, пожалуйста, разобраться...
PM   Вверх
Anikmar
Дата 21.4.2007, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Вот на это ругается:
Цитата(FiMa1 @  21.4.2007,  10:51 Найти цитируемый пост)

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


У вас pa имеет тип *[3], т.е. в каждом элементе указатель на int
А при инициализации вы первому элементу присваиваете a, который имеет тип [3][3];

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


Опытный
**


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

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



Цитата(Anikmar @ 21.4.2007,  10:57)
Вот на это ругается:
Цитата(FiMa1 @  21.4.2007,  10:51 Найти цитируемый пост)

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


У вас pa имеет тип *[3], т.е. в каждом элементе указатель на int
А при инициализации вы первому элементу присваиваете a, который имеет тип [3][3];

Спасибо, но мне изначально было понятно, что в выражении int *pa[3] = { a, a[1], a[2] }; пытаются проинициализировать массив указателей целыми значениями.. Хорошо немного переформулирую вопрос.
Есть следующие объявления переменных:
Код

int a[]  = { 10, 11, 12 };
int *p[] = { a, a+1, a+2 }; //p - массив указателей на int
int **pp = p; //pp - указатель на массив указателей на int

В данном случае, инициализация массива p указателями на элементы ОДНОМЕРНОГО массива a представлена второй строчкой кода.
Теперь есть объявление МНОГОМЕРНОГО массива:
Код

int a[3][3] = { { 11,12,13 },
                       { 21,22,23 },
                       { 31,32,33 }  };

Как правильно проинициализировать массив указателей int *pa[3] элементами a[0][0],  a[1][0] и a[2][0] ?

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


Эксперт
****


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

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



Попробуйте так:
Код

p[0] = a[0];
p[1] = a[1];
p[2] = a[2];


А инициализация {....} на сколько я помню допускается только константами (могу ошибаться - не помню, всегда инициализировал только константами, поэтому вопроса не возникало)
PM MAIL ICQ   Вверх
Dov
Дата 21.4.2007, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(FiMa1 @  21.4.2007,  10:51 Найти цитируемый пост)
int *pa[3] = { a, a[1], a[2] };

FiMa1, выбирай:
Код

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



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
FiMa1
Дата 21.4.2007, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Ok, Dov, спасибо! До первого варианта уже сам додумался, а вот вариант int *pa[3] = { (int*)a, a[1], a[2] };  мне непонятен ... Здесь что указатель приводится к указателю на int? Не понимаю как это работает, поясните плз...

Цитата

А инициализация {....} на сколько я помню допускается только константами 


Anikmar, а что Вас смутило? Где используются НЕ константы?

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


Эксперт
****


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

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



Цитата(FiMa1 @  21.4.2007,  13:17 Найти цитируемый пост)
Anikmar, а что Вас смутило? Где используются НЕ константы?


Смутило, что a[...] может быть не константный. Но я не уверен - поэтому и написал, что точно не уверен.
Хотя если массив объявлен статическим - то наверное константы...
Просто ни разу так не делал - поэтому и засомневался.
PM MAIL ICQ   Вверх
apook
Дата 21.4.2007, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Код

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

Это ни кчемный вариант просто лажа какая-то
Вот самый правильный вариант
Код

int *pa[ 3 ] = { &a[ 0 ][ 0 ], &a[ 1 ][ 0 ], &a[ 2 ][ 0 ] };



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


Опытный
**


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

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



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

int * arr = malloc(100);
free (arr);

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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(FiMa1 @  21.4.2007,  13:17 Найти цитируемый пост)
а вот вариант int *pa[3] = { (int*)a, a[1], a[2] };  мне непонятен ...

Цитата(FiMa1 @  21.4.2007,  13:17 Найти цитируемый пост)
Здесь что указатель приводится к указателю на int? Не понимаю как это работает, поясните плз..

Здесь указатель на указатель на int приводится к указателю на int
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int. Мы его приводим к типу int*, т.е. указатель на int. Почему? Потому, что каждый элемент массива pa[3] имеет тип int*, т.е. указатель на int.



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
FiMa1
Дата 21.4.2007, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(apook @ 21.4.2007,  13:43)
Код

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

Это никчемный вариант просто лажа какая-то
Вот самый правильный вариант
Код

int *pa[ 3 ] = { &a[ 0 ][ 0 ], &a[ 1 ][ 0 ], &a[ 2 ][ 0 ] };

apook, извини, но я не совсем согласен.... Этот вариант можно назвать самым правльным лишь только  с точки зрения читабельности кода. Здесь явно задано, что мы берем адрес элемента [ 0 ][ 0 ] массива а и присваиваем его первому элементу-указателю массива и т.д. для остальных элементов.
Тем не менее запись int *pa[3] = { a[0], a[1], a[2] }; это абсолютно тоже самое тому, что ты написал, т.к. символическое имя a массива - это уже по-сути "скрытый" указатель на первый элемент данного массива. Т.о. указание амперсанда & в начале каждого из элементов a не обязательно.

А вот по-поводу никчемности варианта int *pa[3] = { (int*)a, a[1], a[2] }; вопрос открытый.. Ведь это работает...

Dov однозначно рулит!!! Ему пасиб! Всем оставшимся не равнодушными тоже спасибо. Топик закрыт... 

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


Опытный
**


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

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



 FiMa1  Да ты че не врубаешся в такую ерунду
int a[ 3 ] Dov привел к int *a это сущей воды пурга,
Цитата

*pa[3] = { a[0], a[1], a[2] }; это абсолютно тоже самое тому

если знаешь че тогда спрашиваещ smile


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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(apook @  21.4.2007,  13:43 Найти цитируемый пост)
Это ни кчемный вариант просто лажа какая-то

Ну, что же, apook, у тебя есть 3 варианта.
1. Обосновать своё утверждение и доказать свою правоту, тогда получишь +1 в репу.
2. Не обосновывать и ничего не доказывать, тогда получишь -1 в репу за необоснованый наезд.
3. Ивиниться за необоснованый наезд, тогда не получишь ничего. 

Желаю удачи.  smile 


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
apook
Дата 21.4.2007, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



зачем вносить путанницу вот этим
Код

int *pa[3] = { (int*)a, a[1], a[2] };
 
вариантом.
он вообще тогда не доделан надо так
Код

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

Не надо мугать меня минусами тебе во всякой ерунде наезды чудятся



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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(apook @  21.4.2007,  14:12 Найти цитируемый пост)
Не надо мугать меня минусами тебе во всякой ерунде наезды чудятся

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


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
apook
Дата 21.4.2007, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вынужден признать что моя решчь может показаться наездом
тада извиняй. Но не надо ни минусов не плюсов это не тот случай
Dov "Черт возьми" надеюсь ты не в обиде.....

Это сообщение отредактировал(а) apook - 21.4.2007, 14:29


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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(apook @  21.4.2007,  14:25 Найти цитируемый пост)
Вынужден признать что моя решчь может показаться наездомтада извиняй. Но не надо ни минусов не плюсов это не тот случай

Принято, проехали.  smile 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Rockie
Дата 21.4.2007, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(dizzy1984 @  21.4.2007,  13:46 Найти цитируемый пост)
Насколько я знаю инициализатором переменной в си и си++ выступает любое выражение.

dizzy1984, если сигнатура функции позволяет, то конечно. Но в данном случае
Цитата
Error    1    error C2440: 'initializing' : cannot convert from 'void *' to 'int *





--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
dizzy1984
Дата 21.4.2007, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Rockie @  21.4.2007,  14:37 Найти цитируемый пост)
dizzy1984, если сигнатура функции позволяет, то конечно. Но в данном случае

И в данном случае все верно. Дело в том, что необходимость указания приведения присуща только компиляторам cи++ в си void* приводится к любому другому указателю и без явной указки.
Пардон. Я писал и для того и для другого, тогда, конечно, мой пример работает только для си. Вы правы.

Это сообщение отредактировал(а) dizzy1984 - 21.4.2007, 14:50
PM MAIL   Вверх
Fazil6
Дата 21.4.2007, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  21.4.2007,  13:49 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int. Мы его приводим к типу int*

кто тебе сказал? двумерный массив не тоже самое что указатель на указатель
PM MAIL   Вверх
Dov
Дата 21.4.2007, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  21.4.2007,  15:33 Найти цитируемый пост)
кто тебе сказал? двумерный массив не тоже самое что указатель на указатель

Fazil6, где у меня написано, что двумерный массив это указатель на указатель?  


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 21.4.2007, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Fazil6 @  21.4.2007,  15:33 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int


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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Fazil6, в этой цитате написано, что Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int. Если ты не понимаешь разницу между словами 'массив' и 'имя массива', то почитай какие-нить книжки по этой теме, а потом спрашивай кто мне что сказал.  smile 


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 21.4.2007, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  21.4.2007,  15:51 Найти цитируемый пост)
 Если ты не понимаешь разницу между словами 'массив' и 'имя массива', то почитай какие-нить книжки по этой теме, а потом спрашивай кто мне что сказал.

ну а вот это уже точно наезд... 
И какая же разница в данном случае? Я применил слово массив именно к его имени. И если тебе не нравится формулировка, то имя массива  не тоже самое что указатель на указатель.

это скомпилится?
Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa;

void nn(int **){}


int main()
{
    nn(a);
         aa = a;
    aa = static_cast<int**>(a);
    return 0;

}

как ты думаешь?
PM MAIL   Вверх
Dov
Дата 21.4.2007, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  21.4.2007,  16:01 Найти цитируемый пост)
И какая же разница в данном случае?

Вот видишь, разницу ты не понимаешь. И ещё хочешь о чём-то спорить. Поэтому я тебе и сказал, что бы ты сначала книжки почитал, а потом уже спорил. 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
apook
Дата 21.4.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Осмелюсь вторгнуться в вашу дискуссию чтоб довести до вашего внимания тот факт что имя массива не является переменной.
тогда может ли оно иметь тип? Тип может иметь начальный элемент
массива синонимом расположения в памяти которого я вляется имя
массива, тогда имя массива int а[3][3] имеет тот тип который у а[0] его элемента, а у того тип int a[3], поскольку это не массив указателей, а
именно двумерный массив....или ( smile


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


Опытный
**


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

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



Цитата(apook @ 21.4.2007,  14:12)
зачем вносить путанницу вот этим вариантом.
Код

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

он вообще тогда не доделан надо так
Код

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

 smile Может запоздало комментирую, но вышеприведенная фраза непонятна...
И (int*)a[0]  и a[0] и *a и &(a[0][0]) это ОДНО И ТОЖЕ © Dov.
вообще можем написать:
Код

int *pa[4] = { (int*)a[0] , a[0], *a, &(a[0][0]) };

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

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


Эксперт
***


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

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



Цитата(Dov @  21.4.2007,  16:16 Найти цитируемый пост)
Вот видишь, разницу ты не понимаешь. И ещё хочешь о чём-то спорить. Поэтому я тебе и сказал, что бы ты сначала книжки почитал, а потом уже спорил. 

не цепляйся к словам. Я коментируя твою фразу и в ней указано имя массива и все сказанное мной относится именно к имени массива.
ок. Принимаем, что я ламер без доказательства. 
как насчет компиляции моего примера? 
Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa;

void nn(int **){}


int main()
{
    nn(a);
         aa = a;
    aa = static_cast<int**>(a);
    return 0;

}

в свете того что 
Цитата(Dov @  21.4.2007,  15:51 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int

почему не приводится к int** ?

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


Опытный
**


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

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



Цитата

 Может запоздало комментирую, но вышеприведенная фраза непонятна...

Ну просто нелепо показалось приведение к указателному характеру
одного единственного элемента массива
Код

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

получилось
pa[0]--*a;
pa[1]--a[3];
pa[2]--a[3];
хитро как-то, хотя пускай так будет ладно...

Цитата

И (int*)a[0]  и a[0] и *a и &(a[0][0]) это ОДНО И ТОЖЕ

Это почти одно и то-же, у указателя на массив и массива разный
принцип

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




Это сообщение отредактировал(а) apook - 21.4.2007, 17:12


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


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



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

Имя массива а[][] имеет тип int**

это два разных типа, а второй это как раз указатель на указатель, и это то к чему приципился Fazil6


--------------------
Мой блог
PM MAIL WWW   Вверх
Dov
Дата 21.4.2007, 17:07 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Fazil6, если тебе так сильно хочется поспорить или, что было бы лучше, поучиться чему-нибудь хорошему, то открой соответсвующую тему, зачем же здесь оффтопить.  smile 
По поводу этого.
Цитата(Fazil6 @  21.4.2007,  16:34 Найти цитируемый пост)
почему не приводится к int** ?

попробуй так:
Код

aa = (int**)a;
aa = reinterpret_cast<int**>(a);

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



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
vinter
Дата 21.4.2007, 17:13 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата
попробуй так:код C++
1:
2:
  aa = (int**)a;
aa = reinterpret_cast<int**>(a);


так делать нельзя, они физически в памяти по разному расположены как ты себе представляешь обращение к элементам? вспоминаем арифметику указателей и понимаем почему написали ерунду.
Цитата(Dov @  21.4.2007,  17:07 Найти цитируемый пост)
Ну, а по поводу передачи двумерного массива в ф-цию в качестве аргумента, и здесь на форуме и в инете полным полно разных примеров. Нужно только поиском пользоваться.

тебе бы как раз не мешало бы их поочитать, прежде чем так яростно спорить


--------------------
Мой блог
PM MAIL WWW   Вверх
Dov
Дата 21.4.2007, 17:44 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(vinter @  21.4.2007,  17:13 Найти цитируемый пост)
так делать нельзя

Блин, да что за день сегодня такой.  smile 
vinter, ты вопрос читал? Изначально вопрос звучал так:
Цитата(Fazil6 @  21.4.2007,  16:01 Найти цитируемый пост)
это скомпилится?

Я показал, что скомпилится. 
А описать указатель на двумерный массив можно так, например.
Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int (*aa)[3];
    
aa = a;





--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
vinter
Дата 21.4.2007, 17:46 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(Dov @  21.4.2007,  17:44 Найти цитируемый пост)
vinter, ты вопрос читал?

нет, я читал вашь спор, и исходил только из него.


--------------------
Мой блог
PM MAIL WWW   Вверх
FiMa1
Дата 21.4.2007, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата
Здесь указатель на указатель на int приводится к указателю на int.

Dov, вопросик в догонку - а как выполняется прведение указателя на указатель к у просто указателю.. я не нашел.. Ну в приведении double к int понятно дробная часть откидывается, а здесь не пойму как это срабатывает.. Подскажи плз.
PM   Вверх
Fazil6
Дата 21.4.2007, 18:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  21.4.2007,  17:07 Найти цитируемый пост)
Fazil6, если тебе так сильно хочется поспорить или, что было бы лучше, поучиться чему-нибудь хорошему, то открой соответсвующую тему, зачем же здесь оффтопить.

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

Dov
Я привел конкретный пример и спрашиваю "почему он не компилится?" Я не спрашиваю "как его скомпилировать?" Чувствуешь разницу?
 
reinterpret_cast - это ложь компилятору и с его помощью можно заставить много чего скомпилироваться. 

Цитата(Dov @  21.4.2007,  17:44 Найти цитируемый пост)
Я показал, что скомпилится. 
 
если исправить, то скомпилится , но если 
Цитата(Dov @  21.4.2007,  15:51 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int
, то мой пример должен компиллироваться без изменений. Я ведь пытаюсь использовать имя массива а[][] именно как  int**, но компилятор упорно отказывается. 

Цитата(Dov @  21.4.2007,  14:05 Найти цитируемый пост)
Ну, что же, apook, у тебя есть 3 варианта.1. Обосновать своё утверждение и доказать свою правоту, тогда получишь +1 в репу.2. Не обосновывать и ничего не доказывать, тогда получишь -1 в репу за необоснованый наезд.3. Ивиниться за необоснованый наезд, тогда не получишь ничего. 




PM MAIL   Вверх
apook
Дата 21.4.2007, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Прекращайте этот непонятный спор, я не доволен вашим поведением
это что-за тон, кто вам показал дурацкий пример наезжать друг на друга. smile


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


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


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

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



Цитата(apook @  21.4.2007,  19:54 Найти цитируемый пост)
я не доволен вашим поведением

Эта фраза мне определенно нравится...

Имхо, правда больше на стороне Fazil6 здесь.

Цитата(Fazil6 @  21.4.2007,  18:50 Найти цитируемый пост)
reinterpret_cast - это ложь компилятору и с его помощью можно заставить много чего скомпилироваться. 
 +1.

Цитата(Fazil6 @  21.4.2007,  18:50 Найти цитируемый пост)
Цитата(Dov @  21.4.2007,  15:51 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int

Массив вообще не имеет законченного типа, а уж тем более int**. Этот факт тоже не один раз проскакивал и выяснялся в темах.
Dov, имхо, ты не прав.


Это сообщение отредактировал(а) JackYF - 22.4.2007, 00:27


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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(JackYF @  22.4.2007,  00:09 Найти цитируемый пост)
Dov, имхо, ты не прав.

JackYF, в чём я не прав? 
В этом?
Цитата(JackYF @  22.4.2007,  00:09 Найти цитируемый пост)
Массив вообще не имеет законченного типа, а уж тем более int**.

Так я этого никогда не говорил. Я говорил только про имя массива, которое содержит адрес первого элемента массива, т.е. является указателем. 
Если массив состоит из элементов типа int, то имя массива имеет тип int*, т. е является указателем на 
тип int.
Код

int ar[2]; // массив целых чисел
int* p; // указатель на целое
p = &ar[0]; // р присвоили адрес первого эл-та
р = ar; // то же самое 

Отсюда следует, что и &ar[0] и ar имеют тип  int*, т.к. являются адресами. Абсолютно то же самое можно сказать и про двумерный массив, который, по сути, является одномерным массивом, каждый элемент которого так же является одномерным массивом, и про трёхмерный и т.д.
Код

char* ar[]  = {"qwe", "rty", "asd"}; // одномерный массив типа char* 
char ar1[][4] = {"qwe", "rty", "asd"}; //  он же двумерный массив типа char

И в том, и в другом случае имя массива имеет тип  char**, так как содержит адрес первого элемента массива, который в свою очередь имеет тип char*.
Разыменуем и тот и другой и посмотрим:
Код

cout << *ar  << endl; // получили доступ к элементу ar[0]
cout << *ar1 << endl; // то же самое

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

char ar2[3][4] = { {'q', 'w', 'e'},  "rty",  {'a', 's', 'd'} };
cout << **ar2; // получили доступ к элементу ar2[0][0]


Показал на пальцах, но уж извиняйте, как смог. Добавлю только, что многие не понимают разницу между массивом и именем массива. 
Имя массива - это указатель, хотя и константный, но всё же указатель. Почему? Да хотя бы потому, что содержит адрес, а адреса могут хранить только указатели.
Массив - это последовательность элементов одного и того же типа, имеющих одно имя.
Отсюда следует, что имя массива это только часть массива, и что оно указывает на начало массива.

За сим откланиваюсь и иду спать, ибо лучше объяснить не смогу.  smile 




--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
FiMa1
Дата 22.4.2007, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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




Модератор: Сообщение скрыто.

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


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


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

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



Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
то имя массива имеет тип int*

Нет. Не имеет. Читаем Страуструпа и/или стандарт.



Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
Отсюда следует, что и &ar[0] и ar имеют тип  int*

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

Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
cout << **ar2; // получили доступ к элементу ar2[0][0]

Ха. Это ты к первому элементу матрицы так можешь обратиться через [0][0], так как смещений нет.

Постараюсь показать, что a[x][y] не имеет тип int**
Следующий код принципиально неверен:
Код

int a[10][20];
for (int i = 0; i < 10; ++i)
  for (int j = 0; j < 20; ++j)
    a[i][j] = i*j;

int** b = reinterpret_cast<int**>(a);
for (int i = 0; i < 10; ++i)
  for (int j = 0; j < 20; ++j)
    cout << b[i][j] << ' ';


Вторая часть этого кода работать принципиально не будет.


Это сообщение отредактировал(а) JackYF - 22.4.2007, 12:17


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


Эксперт
***


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

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



Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
Если массив состоит из элементов типа int, то имя массива имеет тип int*, т. е является указателем на тип int.

Код

int arr [] = { 11, 40 };
int* pTr = arr; //неявное преобразование из int [] в int*

Следовательно утверждать, что имя массива имеет типа int* нельзя. К тому же похожий пример есть у Страуструпа - стр. 131

Добавлено @ 13:29
И вообще чего мы так спорим, если есть RTTI?
Код

int arr [] = { 10, 24 };
std::cout << typeid(arr).name();

Выдаст int [2], но никак не int*.

Это сообщение отредактировал(а) Xenon - 22.4.2007, 13:31


--------------------
user posted image  
PM MAIL   Вверх
Fazil6
Дата 22.4.2007, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
Показал на пальцах, но уж извиняйте, как смог. Добавлю только, что многие не понимают разницу между массивом и именем массива. Имя массива - это указатель, хотя и константный, но всё же указатель. Почему? Да хотя бы потому, что содержит адрес, а адреса могут хранить только указатели.

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

Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)

Код

char* ar[]  = {"qwe", "rty", "asd"}; // одномерный массив типа char* 
char ar1[][4] = {"qwe", "rty", "asd"}; //  он же двумерный массив типа char

И в том, и в другом случае имя массива имеет тип  char**, так как содержит адрес первого элемента массива, который в свою очередь имеет тип char*.

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

Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
 Абсолютно то же самое можно сказать и про двумерный массив, который, по сути, является одномерным массивом, каждый элемент которого так же является одномерным массивом, и про трёхмерный и т.д.

вот именно, и что мы имеем? Имя ar1 это указатель на массив char[4]. Где здесь имя, которое можно представлять как указатель?
Запомни : имя двумерного массива интов - это указатель на массив интов, но не как не указатель на указатель на int именно по причине 
Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
 разницу между массивом и именем массива


PM MAIL   Вверх
Xenon
Дата 22.4.2007, 18:05 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Опять же, RTTI :
Код

char ar1[][4] = {"qwe", "rty", "asd"};
std::cout << typeid(ar1).name();

Выдает char[3][4].  Нельзя приравнять два разных типа T[] и T* - это хоть и похожие вещи, но на самом деле разные.


--------------------
user posted image  
PM MAIL   Вверх
Dov
Дата 22.4.2007, 21:50 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Ух, скока накатали. Сразу говорю, что всё ни асилю.  smile 
Цитата(JackYF @  22.4.2007,  12:05 Найти цитируемый пост)
Нет, отсюда это не следует. Я тебе могу написать свой произвольный класс, который будет имитировать точно такое же поведение (возвращение элементов по индексу). Но у него явно не будет тип int*

Оставлю без комментария, хотя этому перлу прямая дорога на башорг, имхо.

Цитата(JackYF @  22.4.2007,  12:05 Найти цитируемый пост)
Ха. Это ты к первому элементу матрицы так можешь обратиться через [0][0], так как смещений нет.

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

cout << **(ar1 + 1) //  доступ к эл-ту ar1[1][0]
cout << *(*(ar1+1)+2)// доступ к эл-ту ar1[1][2]
и т.д.

Цитата(JackYF @  22.4.2007,  12:05 Найти цитируемый пост)
Постараюсь показать, что a[x][y] не имеет тип int**

Каким образом ты это пытался показать, я так и не понял.  smile 

Цитата(JackYF @  22.4.2007,  12:05 Найти цитируемый пост)
Следующий код принципиально неверен
 Вторая часть этого кода работать принципиально не будет.

То, что код не верен, это правда. Но я опять не понял, что именно не работает? Не компилится или не приводится или вывод не работает или выводит, но не правильно? Что не работает?  smile Если хочешь, что бы выводился массив можешь так сделать, например:
Код
cout << *(int*)b + i * 20 + j << ' ';

Или тебе надо, что бы в виде таблицы выводилось? Скажи "принципиально"  smile , что тебе нужно.

Fazil6, весь твой пост оставляю без комментариев, кроме двух фраз, а именно:
Цитата(Fazil6 @  22.4.2007,  17:12 Найти цитируемый пост)
ar1 ну никак не   char**. И все потому, что кое кто действительно не понимает разницу между массивом и именем массива.

Цитата(Fazil6 @  22.4.2007,  17:12 Найти цитируемый пост)
Запомни : имя двумерного массива интов - это указатель на массив интов, но не как не указатель на указатель на int именно по причине разницу между массивом и именем массива

Эти, имхо, на башорг адназначна.  smile
 
Да, а по поводу этого:
Цитата(Fazil6 @  22.4.2007,  17:12 Найти цитируемый пост)
 Имя ar1 это указатель на массив char[4]. Где здесь имя, которое можно представлять как указатель?

Я уже говорил, но для тебя ещё раз повторю. ar1 это указатель на первый элемент массива, т.е. на строку(или массив, если хочешь) "qwe". А имя,  "которое можно представлять как указатель" звучит так(ты не поверишь) : ar1[0] или *ar1, как тебе больше нравится. 

Xenon, с тобой я соглашусь, конечно, но только  не сейчас. По той причине, что  ты не попадаешь в контекст текущей полемики. Здесь идёт разговор о типах данных в плане приведения типов...
 Что-то устал я уже, не могу правильно сформулировать, но это не важно. Ты в самом начале посмотри и всё поймёшь. 
Ну, типа того, что так сделать можно:
Код

char ar[3][4];
char* p = (char*)ar;

а так нельзя:
Код

char ar[3][4];
char[3][4] p = (char[3][4])ar;

А может и можно, но я не знаю как. Тогда покажи.  smile 

Камрады! Желаю всем удачи! 
А я из дискуссии выбываю. Притомился я тут с вами. Всем пока.  smile 


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 22.4.2007, 22:13 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  22.4.2007,  21:50 Найти цитируемый пост)
Я уже говорил, но для тебя ещё раз повторю. ar1 это указатель на первый элемент массива, т.е. на строку(или массив, если хочешь) "qwe". А имя,  "которое можно представлять как указатель" звучит так(ты не поверишь) : ar1[0] или *ar1, как тебе больше нравится. 

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

Цитата(Dov @  22.4.2007,  21:50 Найти цитируемый пост)
Xenon, с тобой я соглашусь, конечно, но только  не сейчас. По той причине, что  ты не попадаешь в контекст текущей полемики. Здесь идёт разговор о типах данных в плане приведения типов...

не работает приведение типов в том виде, в котором ты утверждаешь.

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

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa;

aa = static_cast<int**>(a);

и не приведется именно потому, что твое утверждение по поводу многомерных массивов ошибочно.
Цитата(Dov @  22.4.2007,  02:26 Найти цитируемый пост)
 Абсолютно то же самое можно сказать и про двумерный массив, который, по сути, является одномерным массивом, каждый элемент которого так же является одномерным массивом, и про трёхмерный и т.д.

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

кстати внизу есть ссылки. Вот например и там сразу рассматривается именно этот вопрос
http://forum.vingrad.ru/topic-98636.html



Цитата(Dov @  22.4.2007,  21:50 Найти цитируемый пост)
А я из дискуссии выбываю. Притомился я тут с вами. Всем пока.

а как же  твои слова ???


Цитата(Dov @  21.4.2007,  14:05 Найти цитируемый пост)
1. Обосновать своё утверждение и доказать свою правоту, тогда получишь +1 в репу.
2. Не обосновывать и ничего не доказывать, тогда получишь -1 в репу за необоснованый наезд.
3. Ивиниться за необоснованый наезд, тогда не получишь ничего. 


Цитата(Dov @  21.4.2007,  14:22 Найти цитируемый пост)
Я тебя не пугаю, а учу правилам хорошего тона. Ты должен уметь отвечать за свой базар. Если ты мои слова называешь 'пургой' и 'какой-то лажей', то потрудись, хотя бы это обосновать. 



Это сообщение отредактировал(а) Fazil6 - 22.4.2007, 22:14
PM MAIL   Вверх
apook
Дата 23.4.2007, 04:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

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

Dov Повторяю :указатель это переменная, а имя массива переменной не является(Не по той причине что это константный указатель)
  Есть имя массива a и есть обьект массива с именем a[0], так вот они синонимы, в памяти 
не указывает, а есть начало массива. походу так и рассматривается компилятором.
  Есть указатель pa который являясь указателем выступает в роли имени массива, в памяти
он указывает на начальный элемент массива но сам им не является, он расположен в другом месте.
Код

//блок из 10 последовательных объектов
int a[ 10 ]={ 1, 2, 3, 4, 5, 6, 7, 8, 9 };

//указатель на int
int *pa;
pa=a;
//a=pa не допускается

printf( "%d", *++pa );  //второй элемент массива
printf( "%d", *++a );   //с именем массива a такой номер не пройдет потому-что это не переменная
printf( "%d", *(a+1) ); //хотя так пожалуйста

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

тогда уж имя массива это массив имен переменных smile


Это сообщение отредактировал(а) apook - 23.4.2007, 04:58


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


Опытный
**


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

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



Dov, зачем споришь, если сам давно понял, что неправ? Помог FiMa1 
разобраться - молодец. Но дальше:
Цитата

Здесь указатель на указатель на int приводится к указателю на int 

это как раз ошибка, такое приведение, будь это так, недопустимо.
Fazil6 как раз и указал тебе на это. И привёл короткий и наглядный пример.
Допустим, элемент a[0][0] расположен по адресу 0x00123400. Получаем:
&a[0][0] = 0x00123400; &a[0][1] = 0x00123404; &a[1][0] = 0x0012340C;
a[0] = 0x00123400; a[1] = 0x0012340C;
a = 0x00123400;
*a = 11; (в исходном примере, или 0 в примере Fazil6). 
Именно это и означает, что a - указатель на int, а потому твоё первое 
приведение типа совсем не "пурга", а правильно работает.
Если бы a был указателем на указатель на int, это бы означало, что для 
доступа к этому int нужно брать *(*a), т.е. содержимое с адресом 11 (или 
0). 
Своим спором ты, с одной стороны, теряешь репутацию у тех, кому очевидна 
твоя неправота, с другой, что хуже, запутываешь начинающих. И зачем оно 
тебе надо?

Добавлено через 10 минут и 12 секунд
Для большей аккуратности вместо 
*a = 11;
Следовало бы написать 
*((int*)a) = 11;
PM MAIL   Вверх
dizzy1984
Дата 23.4.2007, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Dov, ты в самом деле не прав [][] и ** это разные типы.
Будет правильно если ты разберешься в теме и тебе, похоже, стоит извениться перед 
Fazil6.
PM MAIL   Вверх
bel_nikita
  Дата 23.4.2007, 11:41 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



дабы прекратить спор раз и навсегд читаем: тут (А разве char a[] не эквивалентно char* a ?)

Это сообщение отредактировал(а) bel_nikita - 24.4.2007, 09:44


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
JackYF
Дата 23.4.2007, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Dov @  22.4.2007,  21:50 Найти цитируемый пост)
Оставлю без комментария, хотя этому перлу прямая дорога на башорг, имхо.

обоснования?

Цитата(Dov @  22.4.2007,  21:50 Найти цитируемый пост)
правильно? Что не работает?  smile

А ты запусти и узнаешь.

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
Цитата(Dov @  22.4.2007,  21:50 Найти цитируемый пост)
А я из дискуссии выбываю. Притомился я тут с вами. Всем пока.

а как же  твои слова ???


Цитата(Dov @  21.4.2007,  14:05 Найти цитируемый пост)
1. Обосновать своё утверждение и доказать свою правоту, тогда получишь +1 в репу.
2. Не обосновывать и ничего не доказывать, тогда получишь -1 в репу за необоснованый наезд.
3. Ивиниться за необоснованый наезд, тогда не получишь ничего. 


Цитата(Dov @  21.4.2007,  14:22 Найти цитируемый пост)
Я тебя не пугаю, а учу правилам хорошего тона. Ты должен уметь отвечать за свой базар. Если ты мои слова называешь 'пургой' и 'какой-то лажей', то потрудись, хотя бы это обосновать. 


+1, поддерживаю.


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


Эксперт
***


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

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



bel_nikita имел ввиду это http://www.rsdn.ru/Forum/Message.aspx?mid=177690&only=1

Это сообщение отредактировал(а) Xenon - 23.4.2007, 18:32


--------------------
user posted image  
PM MAIL   Вверх
Dov
Дата 23.4.2007, 23:01 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
как всетаки сильно желание выдать желаемое за действительное...
Ничего не нужно выдавать. Нужно всего лишь написать одну строку:
Код
cout << *ar1;
и посмотреть, и убедиться, что выведется именно строка "qwe", так как она является первым элементом массива ar1.

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
Я и код привел тебе, на который компиллятор упорно твердит, что int [][] это не int**
Компилятор может и твердит, только я то здесь причём. Если я говорил, что int [][] это int**, то попрошу мою цитату в студию. Я говорил, и буду говорить, что имя массива(в данном случае двумерного массива целых чисел) имеет тип, который по русски называется указатель на указатель на инт, и обозначается так:  int**, подобно тому, как тип целых чисел имеет обозначение(в С/С++) int, а указатель на целое - int*. По этому я могу написать так:
Код
 int** pp = (int**)ar;

 А если ты утверждаешь, что имя массива или же сам массив имеет тип int [][], то покажи мне, как нужно написать. Так, что ли, или как то иначе:
Код
int** pp = (int [][])ar;
 

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
 и никто с тобой не соглашается,
Это да, хотя никто не говорит в чём имеено. Вернее,  не соглашаются в том, чего  я  не говорил. 

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
Почему не компиллируется всетаки мой пример?
А я откуда знаю, это ты должен знать. Мои примеры все компиллируются.

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
не работает приведение типов в том виде, в котором ты утверждаешь.не приведется это код 
Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa;
aa = static_cast<int**>(a);
и не приведется именно потому, что твое утверждение по поводу многомерных массивов ошибочно.
Где я давал этот код? Цитату в студию. Это твой код, а не мой. И я не обязан отвечать за то, что ты пишешь. 

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
имя многомерного массива можно использовать как указатель на его первый элемент
Ну-у-уу, наконец-то дошло.  Я рад.   smile   

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
но 1-м элементом многомерного массива является массив
Если рассматривать его, как одномерный массив массивов(например массив строк), то да. А если просто, как двумерный(например, двумерный массив одиночных символов), то нет. В этом случае 1-м элементом многомерного массива будет элемент с индексом[0][0], т.е. первый одиночный символ этого массива. 

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
,а не имя массива
Имя массива(например, целочисленного, в данном случае), не может быть не только первым, но и вообще никаким элементом массива, по одной простой причине. Имя массива это адрес певого элемена массива, т.е. указатель, а не целое число. Сколько раз я ещё должен это повторять, что бы до вас дошло?  smile 

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
и рассматривать его в свою очередь указателем вкорне неправильно.
 Ур-ра, дошло.  smile Если кто не понял, эта фраза относится к слову 'массив', а не к слову 'имя массива'. 
Совершенно верно, массив это не указатель. Указателем является только адрес первого элемента массива, т.е. его(массива) имя.
Fazil6, как-то полосами до тебя доходит, имхо.  smile 

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
 Ты ведь сам просил не путать массив с его именем
 smile  Вот видишь, я был прав, когда говорил тебе книжки почитать, а ты ещё обижался на меня за это. Ну, ладно, я не в обиде.  smile  

Цитата(Fazil6 @  22.4.2007,  22:13 Найти цитируемый пост)
а как же  твои слова ???
Так это ж я не тебе говорил, а apook`у. Или ты хочешь, что бы я это к тебе применил?  smile  
Кстати, прошу всех обратить внимание на то, что apook  после этого стал намного культурнее в общении, вот посмотрите на его посты до этого и после. Это две большие разницы. 
apook, ты молодец. Стало намного приятнее читать твои посты. Честно.  smile 

Цитата(apook @  23.4.2007,  04:30 Найти цитируемый пост)
Dov Повторяю :указатель это переменная, а имя массива переменной не является(Не по той причине что это константный указатель)
А по поводу этого я скажу тебе так. Указатель, он указатель не потому, что он переменная или константа, или ещё что-то, а потому, что его значением является адрес, понимаешь? адрес той переменной или константы, или ещё чего-нибудь, на которую он указывает. Имя массива это, конечно, не полноценный указатель, у него есть некоторые ограничения, но он хранит адрес и поэтому можно считать его указателем, во всяком случае компилятор именно так и делает.  

Цитата(Ln78 @  23.4.2007,  08:50 Найти цитируемый пост)
Dov, зачем споришь, если сам давно понял, что неправ?
Читай выше.  smile 

Цитата(Ln78 @  23.4.2007,  08:50 Найти цитируемый пост)
это как раз ошибка, такое приведение, будь это так, недопустимо.
Ну, что тут можно сказать? Читай книжки. Пока всё. 

Цитата(Ln78 @  23.4.2007,  08:50 Найти цитируемый пост)
Своим спором ты, с одной стороны, теряешь репутацию у тех, кому очевидна твоя неправота, с другой, что хуже, запутываешь начинающих. И зачем оно тебе надо?
Улыбнуло, даже слов нет.  smile 

Цитата(dizzy1984 @  23.4.2007,  10:30 Найти цитируемый пост)
Dov, ты в самом деле не прав [][] и ** это разные типы.


dizzy1984, читай выше или ткни меня носом, где я говорил, что это одно и то же. Про такой тип int[][], я только в этой теме узнал, что он вобще существует. И до сих пор не могу понять, как можно его, или к нему что-либо привести. 
 
Цитата(dizzy1984 @  23.4.2007,  10:30 Найти цитируемый пост)
Будет правильно если ты разберешься в теме
Лады, постараюсь.  smile 

Цитата(dizzy1984 @  23.4.2007,  10:30 Найти цитируемый пост)
и тебе, похоже, стоит извениться перед Fazil6.
Не вопрос, скажи только в чём я виноват.

Цитата(JackYF @  23.4.2007,  18:12 Найти цитируемый пост)
обоснования?
 JackYF, это моё мнение и я не должен его обосновывать или что-то доказывать, я его просто высказываю. Это не значит, что я хочу тебя чем-то обидеть, боже упаси. Просто, мне это показалось смешным. 

Цитата(JackYF @  23.4.2007,  18:12 Найти цитируемый пост)
А ты запусти и узнаешь
Я то запущу, конечно, но перед этим мне хотелось бы, что бы ты сказал, что твой код должен делать по твоему разумению, но, гадюка такая, не делает. 

Если кому-то не ответил, извините. Вас много, а я один тут за всех отбиваюсь.  smile 
Всем удачи. 

  



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 24.4.2007, 00:13 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Dov, Твое высокомерие переходит всякие границы...

Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
Ничего не нужно выдавать. Нужно всего лишь написать одну строку:
Код

cout << *ar1;

и посмотреть, и убедиться, что выведется именно строка "qwe", так как она является первым элементом массива ar1.

возможно, ты сильно удивишься, но строка "qwe" имеет тип char[4] - и никакой другой (совсем не char*)

Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
Я говорил, и буду говорить, что имя массива(в данном случае двумерного массива целых чисел) имеет тип, который по русски называется указатель на указатель на инт, и обозначается так:  int**, подобно тому, как тип целых чисел имеет обозначение(в С/С++) int, а указатель на целое - int*. По этому я могу написать так


Бред... Ахинея... Приведи мне выдержку из стандарта или цитату из любой книги, где так будет написано (про двумерный массив и его имя и что его имя это указатель на указатель). Это указатель на первый элемент.  А  массив int a[3][3] является одномерным массивом массивов int[3], поэтому первым элементом будет массив и имя а является указателем на int[3] , а это не указатель и поэтому a не является указателем на указатель


Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
Это да, хотя никто не говорит в чём имеено. Вернее,  не соглашаются в том, чего  я  не говорил. 

вот это кто говорил? 
Цитата(Dov @  21.4.2007,  13:49 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int

Именно с этим не соглашаются.


Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
А я откуда знаю, это ты должен знать. Мои примеры все компиллируются.

Ну ты же все знаешь.... Не можешь простейшие ошибки найти в пяти строках?
не компилится именно потому, что имя двумерного массива int не является указателем на указатель int (int**). Именно об этом говорит компилятор. Не надо только приводить доводы, что reinterpret_cast поможет. Если бы твои домыслы были верны, то пример обязан был компилироваться. 

Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)

Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa;
aa = static_cast<int**>(a);

Где я давал этот код? Цитату в студию. Это твой код, а не мой. И я не обязан отвечать за то, что ты пишешь. 

Это мой код. Ты отвечай за себя. Скомпилится Это? a здесь имя массива. По твоему это int**, получается , что одному int** присваивается другой int**,что мешает здесь скомпилироваться? 


Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
Ну-у-уу, наконец-то дошло.  Я рад.


Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
 Ур-ра, дошло.   Если кто не понял, эта фраза относится к слову 'массив', а не к слову 'имя массива'. Совершенно верно, массив это не указатель. Указателем является только адрес первого элемента массива, т.е. его(массива) имя.Fazil6, как-то полосами до тебя доходит, имхо.   

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



Цитата(Dov @  23.4.2007,  23:01 Найти цитируемый пост)
Так это ж я не тебе говорил, а apook`у. Или ты хочешь, что бы я это к тебе применил? 

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




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


Эксперт
***


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

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



вот еще примерчик
Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa = (int**)a;

std::cout << *a   << "\n";  
std::cout << *aa  << "\n";  // фигня выводится и если эту фигню еще вот так  попросить вывестись **aa то получим вообще чпок



Добавлено @ 01:03
Цитата

2.10    Мой компилятор ругается, когда я передаю двумерный массив функции,
    ожидающей указатель на указатель.

О:      Правило, по которому массивы превращаются в указатели не может
        применяться рекурсивно. Массив массивов (т.е. двумерный массив в С)
    превращается в указатель на массив, а не в указатель на    указатель.
    Указатели на массивы могут вводить в заблуждение и применять их    нужно
        с осторожностью. (Путаница еще более усугубляется тем, что существуют
        некорректные компиляторы, включая некоторые версии pcc и полученные
        на основе pcc программы lint, которые неверно вопринимают присваивание
        многоуровневым указателям многомерных массивов.) Если вы передаете
        двумерный массив функции:

  int array[NROWS][NCOLUMNS];
  f(array);

    описание функции должно    соответствовать

   f(int a[][NCOLUMNS]) {...}
    или

                 f(int (*ap)[NCOLUMNS]) {...}   /* ap - указатель на массив */

        В случае, когда используется первое описание, компилятор неявно
        осуществляет обычное преобразование  "массива массивов" в "указатель
        на массив"; во втором случае указатель на массив задается явно.
        Так как вызываемая функция не выделяет место для массива, нет
        необходимости знать  его размер, так что количество "строк" NROWS
        может быть опущено.  "Форма" массива по-прежнему важна, так что
        размер "столбца" NCOLUMNS должен быть включен (а для массивов
        размерности 3 и больше, все промежуточные размеры).

    Если формальный    параметр функции описан    как указатель на указатель,
        то передача функции в качестве параметра двумерного массива будет,
        видимо, некорректной.

        Смотри: K&R I Разд.5.10 c. 110; K&R II Разд.5.9 c. 113.

полный тест http://faqs.org.ru/progr/c_cpp/cfaqrus2.htm



Это сообщение отредактировал(а) Fazil6 - 24.4.2007, 01:04
PM MAIL   Вверх
vinter
Дата 24.4.2007, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



 smile Fazil6, по моему это бесполезно, не трать ты нервы


--------------------
Мой блог
PM MAIL WWW   Вверх
Dov
Дата 24.4.2007, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  24.4.2007,  00:13 Найти цитируемый пост)
Dov, Твое высокомерие переходит всякие границы...
Причём здесь высокомерие?
Fazil6, послушай меня. Вот ты не злись, когда читаешь, то, что я написал, а вдумывайся и старайся понять смысл написанного. Выкинь ты из головы эти стандарты, как будто нет их, ведь для того, что бы понять принцып работы они не нужны. Цитаты из книги я могу тебе дать, но книга написана на иврите. Если ты хочешь, я могу тебе дать цитаты с переводом на русский язык. Книгу написал Йоав Натив, израильский специалист.  Он автор многих книг по программированию, в частности по С/С++, системный аналитик, имеет научную степень. Кстати, это к твоему вопросу о том, кто мне сказал. И вобще, не важно, что кто где сказал. Важно понять, как это всё работает. 

Цитата(Fazil6 @  24.4.2007,  00:13 Найти цитируемый пост)
возможно, ты сильно удивишься, но строка "qwe" имеет тип char[4] - и никакой другой (совсем не char*)

Я понимаю, что компилятор тебе написал  char[4], но ты пойми, он это сделал для того, что бы ты увидел и понял к чему он придрался. Иначе, как он тебе это объяснит? Но сам он воспринимает эту строку именно, как  char*. 

Цитата(Fazil6 @  24.4.2007,  00:13 Найти цитируемый пост)
Это указатель на первый элемент.  А  массив int a[3][3] является одномерным массивом массивов int[3], поэтому первым элементом будет массив и имя а является указателем на int[3] , а это не указатель и поэтому a не является указателем на указатель. 
Fazil6, говоришь ты всё правильно, но понимаешь не верно. Буду думать, как бы получше объяснить... Прийдётся чуть ли не каждом слове останавливаться, ну да ладно, попробую.
Цитата
 А  массив int a[3][3] является одномерным массивом массивов int[3]
Вот этот int[3] тебя и путает, как видно. Давай пока я так скажу.  Массив int a[3][3] можно представить, как  одномерный массив, состоящий из 3 элементов(какого типа эти элементы поговорим ниже, но уж точно не  int[3]), каждый из которых является одномерным массивов, сосоящим из 3 элементов типа  int, т.е. из целых чисел. Стало быть, массив а имеет 3 подмассива(назовём их так, что бы не путаться в тетминах): a[0], a[1], a[2].
Рассмотрим подробнее подмассив а[0]. Это массив из 3 целых чисел типа int. Если а это имя для всего двумерного массива, то а[0] это имя только для этого подмассива. Ко всем трём элементам этого подмассива можно обращаться, указывая его имя а[0] и добавляя к нему индекс элемента. Что бы обратиться, например к последнему элементу, нужно написать a[0][2]. 
Поскольку этот подмассив, по-существу, является обычным  массивом, то его имя а[0] является указателем  на первый элемент а[0][0] и содержит его адрес. В этом легко убедиться. 
Код

 cout << a[0]  << endl;// значение указателя aq[0], хранящее адрес первого элемента подмассива
 cout << &a[0][0] << endl; // адрес первого элемента подмассива

Выведется один и тот же адрес. Делаем вывод, что имя подмассива a[0] является указателем на первый элемент, так как хранит его адрес, поэтому имеет тип указатель на инт, т.е. int*. Это понятно?  
Цитата
поэтому первым элементом будет массив
 Это правильно.
Цитата
и имя а является указателем на int[3]
 Похоже это то место, где ты путаешься. Имя а является указателем не на int[3], а на первый элемент, т.е. на а[0] и содержит его адрес. Это тоже легко проверить. Это то же самое значение, что и в тех двух строчках, которые я привёл выше, т.е. адрес а[0][0], который хренится в указателе а[0].
Код
 cout << a << endl; // значение указателя а, хранящее адрес первого элемента массива
 
Разыменуй его:
Код
 cout << *a << endl;
 И ты увидишь значение указателя а, т.е. адрес, который хранится в указателе а[0]. Это всё тот же адрес элемента с индексом а[0][0].
 Отсюда следует, что имя массива а, указывая на первый элемент т. е. на а[0], является указателем на указатель на инт, потому что, как мы выяснили выше, имя подмассива а[0] это указатель на инт. А поскольку имя массива а это указатель на указатель на инт, то он имеет тип int**. 

Все эти объяснения даны, как бы, с точки зрения компилятора, а не с точки зрения того, кто смотрит на экран монитора и видит там надпись int[][], а что это такое и как его применить он не знает.

Всё, на этом пока остановимся. Если кто не понимает моих объяснений, я не виноват. Я ни кому не навязываю своё мнение. Если кто-то считает, что int[3] или int[333] или int[3][3] это какой-то тип,  к которому можно хоть что-то привести, то ради бога, я не возражаю. Хотелось бы только взглянуть на это приведение.  smile 

Ну, вот. Написал несколько строчек, а потратил на это несколько часов.  smile 

Всем пока.


Извиняюсь, забыл про пример.
Если ты внимательно прочтёшь то, что я написал, то поймёшь, что нужно было бы, хотя бы, написать так:
Код
std::cout << *(int*)aa  << "\n";

А почему, я уже устал объяснять. 
Удачи. 



Это сообщение отредактировал(а) Dov - 24.4.2007, 12:14


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
bel_nikita
Дата 24.4.2007, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Dov
Чтобы понять разницу между int a[] и int *a  -  не нужно никаких книг, и уж тем более цитат. .
Цитата(Dov)
Все эти объяснения даны, как бы, с точки зрения компилятора, а не с точки зрения того, кто смотрит на экран монитора и видит там надпись int[][], а что это такое и как его применить он не знает. 
 Ну, давай посмотрим с точки зрения компилятора. Достачно простого примера и дизасма:
Код
  int a[] = {0,1,2,3,4,5,6,7,8,9};
  int *b = new int[10];
  int aval; int bval;
  aval = a[3];
  bval = b[3];

Смотрим через дизасм: 
Код
;aval = a[3];
mov ecx, dword ptr[ebp-28h]
mov dword ptr[ebp-3Ch], ecx

;bval = b[3];
mov edx, dword ptr[ebp-38h]
mov eax, dword ptr[edx+0Ch]
mov dword ptr[ebp-40h], ecx

Из этого всего видно, что a[3] и b[3] компилятор получает по-разному. 
Когда встречается а[3]: компилятор генерирует код, чтобы считать с позиции a[3]:
1) перемещается на три символа вперед
2) читает требуемый символ.

В случае b[3] компилятор генерирует код, чтобы начать с позиции b:
1) считывает значение указателя
2) прибавляет к указателю 3
3) читает символ, на который указывает указатель.

Т.е. int a[] != int *b.


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Fazil6
Дата 24.4.2007, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  11:59 Найти цитируемый пост)
Я понимаю, что компилятор тебе написал  char[4], но ты пойми, он это сделал для того, что бы ты увидел и понял к чему он придрался. Иначе, как он тебе это объяснит? Но сам он воспринимает эту строку именно, как  char*. 

очень смешно... Сам придумал? Когда-то строки определялись char*, но это было когда-то  и 
Код

char *p = "бла-бла"; // это допустимо сейчас для коректности старого кода


Страуструп. Язык программирования С++. Специальное издание.
стр. 84 
Цитата

3.5.1. С-строки

С-строки  - это массивы символов, ограниченные нулем ($ 5.2.2)....

там же
стр.130
Цитата

5.2.2. Строковые литералы

Строковым литералом называется последовательность символов, заключенная в кавычки:
"Это строка"
.....
Типом строкового литерала есть "массив с надлежащим количеством константных символов"; таким образом "Бор" принадлежит типу const char[4].


Цитата(Dov @  24.4.2007,  11:59 Найти цитируемый пост)
Но сам он воспринимает эту строку именно, как  char*.

нифига подобного. Он воспринимает тип char[n]

вот довольно простой пример
Код

template 
<class T> void f(T &a, T &b)
{
    std::cout << a << "  &  " << b << "   template\n";
}

void f(char *a, char *b)
{
    std::cout << a << "  &  " << b << "   not template\n";    
}

int main()
{
    f("PREVED", "MEDVED");
    f("PREVED", "PREVED111");
    
    return 0;

}

скомпилируй в 7-й или 8-й студии и удивись тому какая вызовется функция в каком варианте и подумай почему имеется именно такая картина. 


Цитата(Dov @  24.4.2007,  11:59 Найти цитируемый пост)
Похоже это то место, где ты путаешься. Имя а является указателем не на int[3], а на первый элемент, т.е. на а[0] и содержит его адрес. Это тоже легко проверить. Это то же самое значение, что и в тех двух строчках, которые я привёл выше, т.е. адрес а[0][0], который хренится в указателе а[0].

ничего я не путаю. Это ты путаешь.
Цитата

5.3 Указатели на масивы
В С++ указатели и массивы тесно связаны. Имя массива можно использовать в качестве указателя на его первый элемент ....

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

Все мои примеры абсурдности твоих умозаключений ты игнорируешь.
 

Цитата(Dov @  24.4.2007,  11:59 Найти цитируемый пост)
Отсюда следует, что имя массива а, указывая на первый элемент т. е. на а[0], является указателем на указатель на инт, потому что, как мы выяснили выше, имя подмассива а[0] это указатель на инт. А поскольку имя массива а это указатель на указатель на инт, то он имеет тип int**. 

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

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


Опытный
**


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

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



Хранятся ли в массиве char[10][10] указатели можно проверить с помощью окна Memory.
PM MAIL   Вверх
Daevaorn
Дата 24.4.2007, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(dizzy1984 @  24.4.2007,  14:55 Найти цитируемый пост)
Хранятся ли в массиве char[10][10] указатели можно проверить с помощью окна Memory.

что за окно?
PM MAIL WWW   Вверх
Dov
Дата 24.4.2007, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



М-да. Как горохом об стену...  smile 

bel_nikita, я тебе про ерёму, а ты мне про фому.  smile Я что, возражаю про то, что ты написал.
Нет. Я вроде бы по-русски пишу, а вы не понимаете. Щас напишу большими буквами, что видно было хорошо. Я говорю, что ИМЯ ОДНОМЕРНОГО МАССИВА ЦЕЛЫХ ЧИСЕЛ - ЭТО УКАЗАТЕЛЬ НА ТИП ИНТ( ПОТОМУ ЧТО ХРАНИТ АДРЕС СВОЕГО ПЕРВОГО ЭТЕМЕНТА, КОТОРЫЙ ИМЕЕТ ТИП ИНТ) И ПО ЭТОМУ ИМЕЕТ ТИП ИНТ*(КАК И ВСЕ ОБЫЧНЫЕ УКАЗАТЕЛИ НА ТИП ИНТ). А ИМЯ ДВУМЕРНОГО МАССИВА ЭТО УКАЗАТЕЛЬ НА УКАЗАЗАТЕЛЬ НА ТИП ИНТ(ПОТОМУ ЧТО ХРАНИТ АДРЕС СВОЕГО ПЕРВОГО ЭТЕМЕНТА, КОТОРЫЙ ИМЕЕТ ТИП УКАЗАЗАТЕЛЬ НА ТИП ИНТ) И ПО ЭТОМУ ИМЕЕТ ТИП ИНТ**(КАК И ВСЕ ОБЫЧНЫЕ УКАЗАТЕЛИ НА ТИП ИНТ*).
И не имеет никакого значения, как был объявлен этот массив, так 
Цитата(bel_nikita @  24.4.2007,  12:38 Найти цитируемый пост)
  int a[] = {0,1,2,3,4,5,6,7,8,9};

или так
Цитата(bel_nikita @  24.4.2007,  12:38 Найти цитируемый пост)
int *b = new int[10];
 Оба имени это указатели на тип инт, а по этому имеют тип инт*, не смотря на те разтичия, что есть между ними.
Ладно, у меня такой вопрос. Есть двумерный статический массив 3х3 .И вот есть такой кусок кода. Вопрос очень простой. Какой тип, по вашему,  имеет указатель pAr и как он был объявлен. Если кому не трудно допишите недостающий код в начале main.
Код

int main()
{
          ...
    
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;
    
    cout << *((int*)pAr + 1) << endl;
    
    return 0;
}
 




--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
likehood
Дата 24.4.2007, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



Цитата(Dov @  24.4.2007,  15:28 Найти цитируемый пост)
и как он был объявлен

да хоть void *pAr;
PM MAIL   Вверх
Dov
Дата 24.4.2007, 14:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Вообще этот разговор похож на это.

А. -  дважды два равно 4.
Б. - нет. трижды три не равно 4.
А. - так я и не говорю, что трижды три равно 4. я говорю, что дважды два равно 4.
Б. - как оно может быть равно 4, если в таблице умножения не написано, что трижды три равно 4.
А. - да выкинь ты свою таблицу умножения, на пальцах прибавь 2 + 2. Будет 4.
Б. - прибавляй, не прибавляй, всё-равно  трижды три не равно 4.

Вот так мы и разговариваем.  smile

Добавлено через 7 минут и 31 секунду
Цитата(likehood @  24.4.2007,  14:35 Найти цитируемый пост)
да хоть void *pAr;

Можно и так, конечно, но давайте пока в рамках int`а, что бы не путаться.  smile 
И как по-русски назвать его тип?

Добавлено через 10 минут и 29 секунд
Вот я, например писал так:
int* это указатель на целое число.
int**  это указатель на указатель на целое число. И т.д.

А вы как назовёте?

Это сообщение отредактировал(а) Dov - 24.4.2007, 14:41


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 24.4.2007, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  14:28 Найти цитируемый пост)
Нет. Я вроде бы по-русски пишу, а вы не понимаете. Щас напишу большими буквами, что видно было хорошо. Я говорю, что ИМЯ ОДНОМЕРНОГО МАССИВА ЦЕЛЫХ ЧИСЕЛ - ЭТО УКАЗАТЕЛЬ НА ТИП ИНТ( ПОТОМУ ЧТО ХРАНИТ АДРЕС СВОЕГО ПЕРВОГО ЭТЕМЕНТА, КОТОРЫЙ ИМЕЕТ ТИП ИНТ) И ПО ЭТОМУ ИМЕЕТ ТИП ИНТ*(КАК И ВСЕ ОБЫЧНЫЕ УКАЗАТЕЛИ НА ТИП ИНТ). А ИМЯ ДВУМЕРНОГО МАССИВА ЭТО УКАЗАТЕЛЬ НА УКАЗАЗАТЕЛЬ НА ТИП ИНТ(ПОТОМУ ЧТО ХРАНИТ АДРЕС СВОЕГО ПЕРВОГО ЭТЕМЕНТА, КОТОРЫЙ ИМЕЕТ ТИП УКАЗАЗАТЕЛЬ НА ТИП ИНТ) И ПО ЭТОМУ ИМЕЕТ ТИП ИНТ**(КАК И ВСЕ ОБЫЧНЫЕ УКАЗАТЕЛИ НА ТИП ИНТ*).

а мы все тебе говорим, что НЕТ, НЕ ТАК. ЭТО ТВОЕ ЗАБЛУЖДЕНИЕ.
Цитата(Dov @  24.4.2007,  14:28 Найти цитируемый пост)

Код

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

Код

int *b = new int[10];


Оба имени это указатели на тип инт, а по этому имеют тип инт*, не смотря на те разтичия, что есть между ними.

Еще раз повторю, в первом случае имя может использоваться КАК указатель, а тип у него int[10] и правило по поводу имени массива нерекурсивно и имя многомерного массива не может использоваться как указатель на указатель и т.д. А все приемы типа явного приведения 
Код

int a[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
int **aa = (int**)a;

std::cout << *a   << "\n";  
std::cout << *aa  << "\n";  // фигня выводится и если эту фигню еще вот так  попросить вывестись **aa то получим вообще чпок

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

Добавлено через 31 секунду
Цитата(Dov @  24.4.2007,  14:40 Найти цитируемый пост)
Вот я, например писал так:int* это указатель на целое число.int**  это указатель на указатель на целое число. И т.д.А вы как назовёте?

и при чем здесь массивы?
PM MAIL   Вверх
Dov
Дата 24.4.2007, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  24.4.2007,  14:52 Найти цитируемый пост)
и при чем здесь массивы?

Я про pAr спрашиваю.

Добавлено через 3 минуты и 51 секунду
Цитата(Fazil6 @  24.4.2007,  14:52 Найти цитируемый пост)
В этом примере, например, выведется совершенно разный результат.


Fazil6, в предыдущем своём посте я тебе показал, как нужно делать. Или в предпредыдущем.


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 24.4.2007, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Код

int main()
{
         int pAr[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
    
    
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;

    cout << *((int*)pAr + 1) << endl;
    return 0;
}


ну вот  так будет работать видимо как ты хотел показать. pAr здесь типа int[3][3], использовать можно как указатель на int[3].
Не совсем понимаю что ты хотел продемонстрировать.
Код

*(int*)pAr = 6;

правое выражение вполне нормально интерпретируется как значение инта по какому-то адресу... Ну продемонстрировал ты что элемент массива можно проинициализировать через одно место... Ну и что? Работает это потому же почему
Код

cout << pAr << endl;
cout << *pAr << endl;

выдаст абсолютно одно и тоже именно потому, что pAr массив

Добавлено через 7 минут и 21 секунду
Цитата(Dov @  24.4.2007,  14:58 Найти цитируемый пост)
Fazil6, в предыдущем своём посте я тебе показал, как нужно делать. Или в предпредыдущем.

то чтоли?
Код

std::cout << *(int*)aa  << "\n";

и где здесь указатель на указатель?
тут сказано, что значение в aa считать указателем на инт и вывести значение по этому адресу.  И что? Ну обманул ты компилятор...  Разве это что-то доказывает?


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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Fazil6, совершенно верно, именно это я и хотел увидеть. Что бы показать ещё и такой код:
Код
int main()
{
    int p[3][3];
    int** pAr = (int**)p; 
    
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;
    
    cout << *((int*)pAr + 1) << endl;
    
    return 0;
}


Теперь ты воочию можешь убедиться, что для компилятора без разницы, как был объявлен pAr. Главное это как его воспринимает компилятор. А для него это тип  int**. 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 24.4.2007, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  15:29 Найти цитируемый пост)
Теперь ты воочию можешь убедиться, что для компилятора без разницы, как был объявлен pAr. Главное это как его воспринимает компилятор. А для него это тип  int**. 

ха-ха... Зачем же ты его везде приводишь к int* ? Действительно для компилятора без разницы. Ты ведь заткнул ему рот явными приведениями совершенно к другому типу. И он его воспринимает именно как int* везде кроме объявления pAr
Код

int** pAr = (int**)p;  // тут ты заставил pAr и p указывать на одну область памяти


cout << *pAr << endl; // удивись что выведется
cout << **pAr << endl; // чпок !!!



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


666
**


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

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



Кстати, так тоже работает:
Код

int main()
{
    int p[3][3];
    double*** pAr = (double***)p; 
    
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;
    
    cout << *((int*)pAr + 1) << endl;
    
    return 0;
}

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


Эксперт
***


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

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



это как раз и доказывает, что int p[3][3]; никаким способом в int** не превратить
PM MAIL   Вверх
bel_nikita
Дата 24.4.2007, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Dov,
Цитата(Dov @ 24.4.2007,  13:28)
Я говорю, что ИМЯ ОДНОМЕРНОГО МАССИВА ЦЕЛЫХ ЧИСЕЛ - ЭТО УКАЗАТЕЛЬ НА ТИП ИНТ( ПОТОМУ ЧТО ХРАНИТ АДРЕС СВОЕГО ПЕРВОГО ЭТЕМЕНТА, КОТОРЫЙ ИМЕЕТ ТИП ИНТ) И ПО ЭТОМУ ИМЕЕТ ТИП ИНТ*(КАК И ВСЕ ОБЫЧНЫЕ УКАЗАТЕЛИ НА ТИП ИНТ). 

Повторюсь еще раз, 
Код
int a[3]; // эквивалент указателя
int *b; // указатель

Но если по-твоему int a[3] это обычный указатель int*, тогда объясни всему миру почему не прокатывает: 
Код
  int a[10] = {0,1,2,3,4,5,6,7,8,9};
  int *b = new int[10];
  a = b;


Цитата(Dov @ 24.4.2007,  13:28)

совершенно верно, именно это я и хотел увидеть. Что бы показать ещё и такой код:
Код
int main()
{
    int p[3][3];
    int** pAr = (int**)p; 
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;
    cout << *((int*)pAr + 1) << endl;
    return 0;
}


Зашибись! Напиши pAr[1][1] = 1; и удивись smile 


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Dov
Дата 24.4.2007, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  24.4.2007,  15:42 Найти цитируемый пост)
это как раз и доказывает, что int p[3][3]; никаким способом в int** не превратить

Хорошо, тогда скажи мне, что тебя может убедить в том, что имя двумерного массива это указатель на указатель? 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
likehood
Дата 24.4.2007, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



Цитата(Dov @  24.4.2007,  16:57 Найти цитируемый пост)
Хорошо, тогда скажи мне, что тебя может убедить в том, что имя двумерного массива это указатель на указатель? 

Если бы его можно было присвоить указателю на указатель и потом работать с этим указателем как с обычным двумерным массивом.
PM MAIL   Вверх
Dov
Дата 24.4.2007, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



bel_nikita, ну ёлы-палы, ну сколько можно?
Цитата(bel_nikita @  24.4.2007,  15:55 Найти цитируемый пост)
Но если по-твоему int a[3] это обычный указатель int*, тогда объясни всему миру почему не прокатывает: 


Цитату в студию, где я такое говорил? Только перед тем, как её постить, посмотри, что там написано, я тебя очень прошу.  


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Fazil6
Дата 24.4.2007, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  15:57 Найти цитируемый пост)
Хорошо, тогда скажи мне, что тебя может убедить в том, что имя двумерного массива это указатель на указатель? 


ну, например если бы компиллировалось
Код

int p[3][3];
int** pAr = p; 

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

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

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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



likehood, тогда скажи мне, что же это такое указатель на указатель В твоём понимании, конечно. И какой тип он имеет.
 А заодно скажи мне, что такое указатель,  опять же в твоём понимании. 
Возможно, мы оперируем разными терминами? Я своё определение уже дал.

Добавлено через 3 минуты и 55 секунд
Fazil6, ты тоже скажи, если не трудно, про то, что я спросил у likehood.


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
dizzy1984
Дата 24.4.2007, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Daevaorn, Имелось в виду средство для просмотра памяти отладчика vs.
View->Debug Windows->Memory (alt+6).
С его помощью можно было бы посмотреть для случая char arr[10][10]={'a','b','c','d'}.
На место памяти arr. Там должен был бы быть адрес одномерного массива, если бы был прав 
Dov, либо 'a''b''c''d', если бы был прав Fazil6.
PM MAIL   Вверх
Fazil6
Дата 24.4.2007, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  16:12 Найти цитируемый пост)
 что же это такое указатель на указатель В твоём понимании, конечно. И какой тип он имеет. А заодно скажи мне, что такое указатель,  опять же в твоём понимании. 

меня вполне устраивает тот смысл, который ты вкладываешь в указатели. Меня неустраивает то как ты легко мешаешь указатели, массивы и их имена(которые могут использоваться как указатели). 


Цитата(Dov @  21.4.2007,  13:49 Найти цитируемый пост)
Имя массива а[][] имеет тип int**, т.е. указатель на указатель на int. Мы его приводим к типу int*, т.е. указатель на int. Почему? Потому, что каждый элемент массива pa[3] имеет тип int*, т.е. указатель на int.

это неверно и безграмотно.
PM MAIL   Вверх
bel_nikita
Дата 24.4.2007, 16:37 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Dov,
Цитата(Dov @ 24.4.2007,  13:28)
Цитату в студию, где я такое говорил? Только перед тем, как её постить, посмотри, что там написано, я тебя очень прошу. 
И я тебя очень прошу: Перед тем, как постить, посмотри, что написал.
Цитата(Dov @ 24.4.2007,  13:28)
Я говорю, что ИМЯ ОДНОМЕРНОГО МАССИВА ЦЕЛЫХ ЧИСЕЛ - ЭТО УКАЗАТЕЛЬ НА ТИП ИНТ( ПОТОМУ ЧТО ХРАНИТ АДРЕС СВОЕГО ПЕРВОГО ЭТЕМЕНТА, КОТОРЫЙ ИМЕЕТ ТИП ИНТ) И ПО ЭТОМУ ИМЕЕТ ТИП ИНТ*(КАК И ВСЕ ОБЫЧНЫЕ УКАЗАТЕЛИ НА ТИП ИНТ).


Итак, вернемся к дискусии.
Хорошо, по-твоему int a[] == int *b, т.е. int a[] - указатель и int*b - указатель. Тогда объясни мне, пожалуйста, почему не прокатывает следующее: 
Код

  int a[10] = {0,1,2,3,4,5,6,7,8,9};
  int *b = new int[10];
  a = b; // Ведь мы просто пытаемся приравнивать "указатель" к указателю.


И еще вернемся к твоему примеру, 
Код
int main()
{
    int p[3][3];
    int** pAr = (int**)p; 
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;
    pAr[1][1] = 1; // Ба-Бах!
    cout << *((int*)pAr + 1) << endl;
    return 0;
}

Обясни, пожалуйста, почему происходит Ба-Бах! в 7-ой строке?

З.Ы.: Dov, ты все просишь, чтоб другие отвечали на твои вопросы: что же это такое указатель на указатель; что такое указатель и т.д.
И я тебя прошу: ответь хоть на один мой вопрос, вместо очередного увиливания от ответа и придирки к словам.



--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Dov
Дата 24.4.2007, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



bel_nikita, не в обиду тебе, скажу. Во всей этой теме есть всего десяток моих постов. Там есть все ответы на твои вопросы. Там написано, что такое массив и что такое имя массива. Там написано, что имя массива, хоть и указатель, но константный, поэтому и не будет работать твоё присваивание, ну и так далее. Сначала нужно почитать всё внимательно, а потом уже обвинять меня в том, чего я не говорил. А то получается так, читать не хотим, давай рассказывай нам в 1000-й раз одно и тоже. Вы что думаете, мне больше заняться нечем ? 
Убил здесь столько времени и всё заново начинать. Так что ли? Нет уж, надоело.
Повторю ещё раз то, что я сказал раньше.  
Цитата(Dov @  24.4.2007,  11:59 Найти цитируемый пост)
 Если кто не понимает моих объяснений, я не виноват. Я ни кому не навязываю своё мнение. Если кто-то считает, что int[3] или int[333] или int[3][3] это какой-то тип,  к которому можно хоть что-то привести, то ради бога, я не возражаю. Хотелось бы только взглянуть на это приведение.


Всё сказанное в этой теме, моё личное, персональное имхо. всем удачи.



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Daevaorn
Дата 24.4.2007, 17:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Dov, жесть. Чушь несешь полную. Почитай перед сном стандарт. Должно вылечить.
PM MAIL WWW   Вверх
Ln78
Дата 24.4.2007, 17:34 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



smile Ребята, давайте закончим эту дискуссию. Ежу понятно, что главное в последнем посте bel_nikita, это 7-я строчка его примера. Это - единственное, 100%-е и безусловное доказательство того, что приведение в 4-й строчке разумно, если бы оно работало. Тому же ежу понятно, что оно не работает. Dov, безусловно, умнее ежа. Просто сказать, "Извините, господа, #уйню спорол-с" ну не как не получится. И последнее слово он хочет, во что бы то ни стало оставить за собой. Ну и ладно, пусть так и будет

Добавлено через 3 минуты и 13 секунд
Для большей строгости, конечно, лучше
Код

pAr[0][1] = 1; // Ба-Бах!

но это дело не меняет
PM MAIL   Вверх
Fazil6
Дата 24.4.2007, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  17:04 Найти цитируемый пост)
Там есть все ответы на твои вопросы.

на большинство нету. Ни на чьи вопросы, которые неудобны и действительно противоречат твоим теориям ты не ответил...
Своих внятных примеров ты не привел. Если привел, то дай хотябы одну ссылку.
PM MAIL   Вверх
Xenon
Дата 24.4.2007, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(bel_nikita @  24.4.2007,  16:37 Найти цитируемый пост)
Хорошо, по-твоему int a[] == int *b, т.е. int a[] - указатель и int*b - указатель.

Если бы было так, то ... 
Код

int arr [] = { 2, 4 , 5 };
int arr2 [][2] = { {2,5}, {4,6} };
int* pTr = arr;
int** pTr2 = 0;
std::cout.setf(std::ios::boolalpha);
std::cout << "int [] == int* - " << ( sizeof(arr)/sizeof(int) == sizeof(pTr)/sizeof(int) ); //Почему не равен размер?
std::cout << "\nint [] == int* - " << (typeid(arr).name() == typeid(pTr).name()); //Почему int [] != int* ?
std::cout << "\nint [][] == int** - " << (typeid(arr2).name() == typeid(pTr2).name()); //Почему int[][] != int** ?

Почему-то всегда выдает false smile

bel_nikita, в твоем примере
Код

int a[10] = {0,1,2,3,4,5,6,7,8,9};
int *b = new int[10];
a = b; // Ведь мы просто пытаемся приравнивать "указатель" к указателю.

можно оправдаться и сказать, что a имеет тип int* const pTr, поэтому присваивание невозможно smile 

Это сообщение отредактировал(а) Xenon - 24.4.2007, 19:21


--------------------
user posted image  
PM MAIL   Вверх
Dov
Дата 24.4.2007, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  24.4.2007,  16:08 Найти цитируемый пост)
ну, например если бы компиллировалоськод
Код

int p[3][3];
int** pAr = p;
то я вынужден был бы признать, что ничего не понимаю и не знаю.

Ты хоть понимаешь, что ты здесь написал. Ты пытаешься указателю на указатель на инт присвоить адрес двумерного массива. То есть, грубо говоря, вместо int** ты ему подсовываешь int*** и хочешь, что бы это работало. Без приведения это работать не будет. Такому указателю ты можешь присвоить адрес указателя на подмассив массива, но не как не адрес самого массива. Например, ты можешь сделать так:
Код

int p[3][3];
int* pp = p[0]; 
int** pAr = &pp;

Ну, или извращаться и использовать приведение...   

Цитата(Fazil6 @  24.4.2007,  16:08 Найти цитируемый пост)
Со мной, например, кроме тебя никто не спорит в этой ветке.
Fazil6, я тоже с тобой не спорю, я,лишь, высказываю своё мнение.  smile И каждый вправе соглашаться с ним или нет. 
Цитата(Fazil6 @  24.4.2007,  16:36 Найти цитируемый пост)
меня вполне устраивает тот смысл, который ты вкладываешь в указатели.
Хорошо.

Цитата(Fazil6 @  24.4.2007,  16:36 Найти цитируемый пост)
Меня неустраивает то как ты легко мешаешь указатели, массивы и их имена(которые могут использоваться как указатели). 
Твоё право.

Цитата(bel_nikita @  24.4.2007,  16:37 Найти цитируемый пост)
Обясни, пожалуйста, почему происходит Ба-Бах! в 7-ой строке?
А самому что, никак не разобраться?  smile  Посмотри тогда в одном из моих постов на 2-3 странице, как нужно описать указатель на двумерный массив, что бы он работал так, как ты хочешь.  

Цитата(Daevaorn @  24.4.2007,  17:34 Найти цитируемый пост)
Dov, жесть. Чушь несешь полную. Почитай перед сном стандарт. Должно вылечить.
 Слушаюсь, товарищ майор. Разрешите выполнять?

Так, а теперь к делу.
Цитата(Fazil6 @  24.4.2007,  14:52 Найти цитируемый пост)
 мы все тебе говорим, что НЕТ, НЕ ТАК. ЭТО ТВОЕ ЗАБЛУЖДЕНИЕ.

Цитата(Fazil6 @  24.4.2007,  14:52 Найти цитируемый пост)
имя многомерного массива не может использоваться как указатель на указатель

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

Если есть такой код:
Код

int var = 5;
int* p = &var; // в р хранится адрес var.
int var1= *p; // var1 == 5
int** pp = &p;// в рр хранится адрес указателя р.
int* p2 = *pp;       // в р2 хранится адрес указателя р.
int var2 = *p2; // var2== 5
int var3 = *(*рр); // var3 == 5 
то это значит.
2. Значением указателя р будет выражение &var, то есть адрес переменной var.
3. Значение по этому адресу можно получить разыменовав указатель р.
4.Доказательством того, что р является указателем служит тот факт, что переменной var2 было присвоено значение 5, которое хранится в ячейке памяти, на которую указывает р, то есть значение переменной var.
5. Разыменование указателя р, то есть получение значения с той ячейки памяти, на которую он указывает это доказательство того, что р это указатель на int. 
6. Поскольку рр содержит адрес указателя р, который является указателем на int, то это доказательтство того, что рр является указателем на указатель на int. 
7. Разыменование указателя рр, то есть получение значения с той ячейки памяти, на которую он указывает это доказательство того, что рр это указатель на указатель на int. 
8. Если значение переменной var3 равно значению var, то это доказательство того, что рр это укзатеть на указатель на int, поскольку через указатель рр мы получили значение ячейки, на которую указывает указатель р, являющийся указателем на int.
9. Таким образом выражение var3 = *(*рр) это доказательство того, что рр это указатель на указатель на int. 

Я хочу знать кто с чем не согласен.
Кто хочет поучаствовать пишите всего два слова, номер утверждения и ответ на него, т.е. да или нет.
Например:
1. нет
2. да 
и т.д.

На сегодня всё, ребятки. Пошёл читать устав, или как там его. А, вспомнил. Стандарт. 
Всем пока. И удачи... в изучении стандарта.  smile 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
JackYF
Дата 25.4.2007, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
ы хоть понимаешь, что ты здесь написал. Ты пытаешься указателю на указатель на инт присвоить адрес двумерного массива. То есть, грубо говоря, вместо int** ты ему подсовываешь int***


Ну где, где ты там увидел int***?



Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
А самому что, никак не разобраться?

Мы уже разобрались. Мы просим тебя ответить.



Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
Я сказал, что имя двумерного целочисленного массива имеет тип указатель на указатель на инт. Именно эти мои слова считают здесь чушью и бредом.


Тебе уже не раз говорили. Еще раз повторяю. Имя массива вообще не имеет законченного типа! Кури стандарт.

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
Если есть такой код:

У тебя в коде ни одного массива. Спасибо за работу с указателями. Мы говорим про массивы, не так ли?

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
На сегодня всё, ребятки. Пошёл читать устав, или как там его. А, вспомнил. Стандарт. 
Всем пока. И удачи... в изучении стандарта.  smile 

Привыкай. Устав - не устав, но против стандарта не попрешь. MFC - это еще не все.



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


Опытный
**


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

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



Клевый спор smile
Цитата

имя может использоваться КАК указатель

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

Цитата

В этом случае 1-м элементом многомерного массива будет элемент с индексом[0][0], т.е. первый одиночный символ этого массива.

Dov интересная гипотеза?
Я думаю что 1-м элементом многомерного массива a[3][3] будет обьект с именем a[3], который
в свою очередь содержит адрес элемента с индексом 0.

Цитата

Выкинь ты из головы эти стандарты

Dov я тебя понял smile в предложениях абстрогироваться от стандартов, некий дух ХИППИ
Проникнувшись этим я утверждаю что не существует типа int[3][3] и int*, а есть int и все
остальные значки это прибамбасы! И буду в чем-то прав.
 
Бывает...




Dov Хочется поставить плюсик но ситуация не позволяет, все же ты не прав


Это сообщение отредактировал(а) apook - 25.4.2007, 04:45


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



****


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

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



Цитата(apook @  25.4.2007,  03:54 Найти цитируемый пост)
Dov Хочется поставить плюсик но ситуация не позволяет, все же ты не прав

да, Dov, ты не прав smile. Переливаете из пустого в порожнее, шесть страниц накатали уже, лучше бы программы писали smile
PM MAIL   Вверх
Kipter
Дата 25.4.2007, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Да ладно вам, застыдили Dov'a...
Он понимает как это работает и саму суть.... только с теорией плохо....
PM MAIL   Вверх
Fazil6
Дата 25.4.2007, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
Ты хоть понимаешь, что ты здесь написал. Ты пытаешься указателю на указатель на инт присвоить адрес двумерного массива. То есть, грубо говоря, вместо int** ты ему подсовываешь int*** и хочешь, что бы это работало. Без приведения это работать не будет. Такому указателю ты можешь присвоить адрес указателя на подмассив массива, но не как не адрес самого массива. Например, ты можешь сделать так:

Мда... Вот это уже точно жесть.... Такого отвязного бреда еще небыло в этой ветке.... Ты же все время утверждал, что имя двумерного массива является int**... Теперь это у тебя 
Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
адрес двумерного массива

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
То есть, грубо говоря, 

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
int***


ты уж определись какой бред тебе ближе.

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
Без приведения это работать не будет.

Жесть... С приведением это будет компиллироваться. Работать это никогда не будет. Именно поэтому ты и не докажешь никому ничего.

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
и хочешь, что бы это работало

и где я сказал, что хочу чтобы это работало? Я сказал, что по твоей теории это правильный код 

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
А самому что, никак не разобраться?    Посмотри тогда в одном из моих постов на 2-3 странице, как нужно описать указатель на двумерный массив, что бы он работал так, как ты хочешь.  

как правильно с массивами работать все понимают, вот только там нигде нет указателей на указатель как ни крути и не приводи.

Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)
то это значит.2. Значением указателя р будет выражение &var, то есть адрес переменной var.3. Значение по этому адресу можно получить разыменовав указатель р.4.Доказательством того, что р является указателем служит тот факт, что переменной var2 было присвоено значение 5, которое хранится в ячейке памяти, на которую указывает р, то есть значение переменной var.5. Разыменование указателя р, то есть получение значения с той ячейки памяти, на которую он указывает это доказательство того, что р это указатель на int. 6. Поскольку рр содержит адрес указателя р, который является указателем на int, то это доказательтство того, что рр является указателем на указатель на int. 7. Разыменование указателя рр, то есть получение значения с той ячейки памяти, на которую он указывает это доказательство того, что рр это указатель на указатель на int. 8. Если значение переменной var3 равно значению var, то это доказательство того, что рр это укзатеть на указатель на int, поскольку через указатель рр мы получили значение ячейки, на которую указывает указатель р, являющийся указателем на int.9. Таким образом выражение var3 = *(*рр) это доказательство того, что рр это указатель на указатель на int. Я хочу знать кто с чем не согласен.

воттолько причем здесь массивы и их имена?  smile 

Цитата(apook @  25.4.2007,  03:54 Найти цитируемый пост)
не имя может использоваться как указатель, а указатель можетиспользоваться в качестве имени, а имя не есть указатель, асодержит адрес первого элемента массива.

эх, зря ты это написал...

Добавлено через 1 минуту и 36 секунд
Цитата(Kipter @  25.4.2007,  08:44 Найти цитируемый пост)
Он понимает как это работает и саму суть.... только с теорией плохо....

похоже, нихрена он не понимает...
PM MAIL   Вверх
bel_nikita
Дата 25.4.2007, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Dov,
Цитата(Dov @ 24.4.2007,  22:43)
Цитата(Daevaorn @  24.4.2007,  17:34 Найти цитируемый пост)
Dov, жесть. Чушь несешь полную. Почитай перед сном стандарт. Должно вылечить.
 Слушаюсь, товарищ майор. Разрешите выполнять?

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

Не съезжай всторону. Чушью и бредом считают твой приведенный код. Вот, некоторый фрагмент:
Код
int main()
{
    int p[3][3];
    int** pAr = (int**)p; 
    *(int*)pAr = 6;
    *((int*)pAr + 1) = 8;
    cout << *((int*)pAr + 1) << endl;
    return 0;
}


Dov, почитал твои посты... И скажу твоими же цитатами: 
Цитата(Dov @ 21.4.2007, 13:05)
1. Обосновать своё утверждение и доказать свою правоту, тогда получишь +1 в репу.
2. Не обосновывать и ничего не доказывать, тогда получишь -1 в репу за необоснованый наезд.
3. Ивиниться за необоснованый наезд, тогда не получишь ничего. 
Желаю удачи.  smile  
Ответь сам себе на свои же наезды smile 

З.Ы.: 
Цитата(Dov @ 21.4.2007, 13:22)
Я тебя не пугаю, а учу правилам хорошего тона. Ты должен уметь отвечать за свой базар.




--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Fazil6
Дата 25.4.2007, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(bel_nikita @  25.4.2007,  09:58 Найти цитируемый пост)
Не съезжай всторону. Чушью и бредом считают твой приведенный код.

те слова тоже бред и чушь
PM MAIL   Вверх
dizzy1984
Дата 25.4.2007, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



А что интересно так, когда скучно становится всегда знаешь что почитать...  smile 
PM MAIL   Вверх
FiMa1
Дата 25.4.2007, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Программа динамического размещения трехмерного массива. Вываливается Debug Assertion Failed при "освобождении памяти, выделенной под указатели на столбцы одномерных массивов" (сорри за корявый коммент).
Не пойму что не так делаю, поправьте, меня плз...

Код

#include <iostream>
#include <iomanip>
using namespace std;

int main(void)
{    
    int str = 3, row = 3, tdim = 3;
    double ***a;
    int i, j, k;

    /* ВЫДЕЛЕНИЕ ПАМЯТИ ДЛЯ МАТРИЦЫ */
    // резервирование памяти под указатели на строки матрицы
    a = new double**[str];
    
    // резервирование памяти под указатели на столбцы одномерных массивов
    for( i = 0; i < str * row; i++ )
        *(a + i) = new double*[row];
    
        // резервирование памяти под фактические данные матрицы
        for( i = 0; i < str * row; i++ )
            **(a + i)  = new double[row];//или *a[i] = ...

        /* ИНИЦИАЛИЗАЦИЯ МАТРИЦЫ */
        for( i = 0; i < str; i++ )
            for( j = 0; j < row; j++ )
                for( k = 0; k < tdim; k++ )
                    ***(a + i + j + k ) = rand() % 100;

        /* ПЕЧАТЬ МАТРИЦЫ */
        for( i = 0; i < str; i++)
        {
            for( j = 0; j < row; j++ )
                for( k = 0; k < tdim; k++ )
                    cout << setw(4) << ***(a + i + j + k );
                cout << endl;
            cout << endl;
        }

        /* ОСВОБОЖДЕНИЕ ПАМЯТИ, ВЫДЕЛЕННОЙ ДЛЯ МАТРИЦЫ */
        for( i = 0; i < str * row; i++ )
        // освобождение памяти, выделенной под фактические данные матрицы
            delete[] **(a + i);

        for( i = 0; i < str; i++ )
        // освобождение памяти, выделенной под указатели на столбцы одномерных массивов
            delete[] *(a + i);

        // освобождение памяти, выделенной под указатели на строки матрицы
        delete[] a;

    return 0;
}


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


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


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

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



Цитата(FiMa1 @  25.4.2007,  14:41 Найти цитируемый пост)
Не пойму что не так делаю, поправьте, меня плз...




Цитата(FiMa1 @  25.4.2007,  14:41 Найти цитируемый пост)
 for( i = 0; i < str * row; i++ )
            **(a + i)  = new double[row];//или *a[i] = ...


Вот тут неверно. Инициализация делается отдельными тремя циклами. Надо так:

Код

 a = new double**[str];
    
    // резервирование памяти под указатели на столбцы одномерных массивов
    for( i = 0; i < str; i++ )
        a[i] = new double*[row];
    
        // резервирование памяти под фактические данные матрицы
        for( i = 0; i < str; i++ )
          for( j = 0; j < row; ++j )
            a[i][j]  = new double;



Это сообщение отредактировал(а) JackYF - 25.4.2007, 15:08


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


Эксперт
****


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

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



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

void main(void )
{
    int Size0 = 5;
    int Size1 = 5;
    int Size2 = 5;
    double ***aMas;
    int i,j,k;

    // Создание массива
    aMas = new double**[Size0];
    for (i=0;i<Size0;i++)
    {
        aMas[i] = new double* [Size1];
        for(j=0;j<Size1;j++)
            aMas[i][j] = new double[Size2];
    }

    // Заполнение элементами
    for (i=0;i<Size0;i++)
        for(j=0;j<Size1;j++)
            for(k=0;k<Size2;k++)
                aMas[i][j][k] = rand() % 100;

    // Вывод на экран
    for (i=0;i<Size0;i++)
        for(j=0;j<Size1;j++)
        {
            cout << endl;
            for(k=0;k<Size2;k++)
                cout << "[" << i << "][" << j << "][" << k << "]=" << aMas[i][j][k] << " ";
        }

    // Удаление
    for (i=0;i<Size0;i++)
    {
        for(j=0;j<Size1;j++)
            delete [] aMas[i][j];
        delete [] aMas[i];
    }
    delete [] aMas;

    getch();
}



Добавлено через 39 секунд
Правда мой вывод отличается от того, что надо, ну и размеры 5.5.5 можно другие поставить
PM MAIL ICQ   Вверх
FiMa1
Дата 25.4.2007, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(JackYF @ 25.4.2007,  15:07)
Надо так:
Код

 a = new double**[str];
    
    // резервирование памяти под указатели на столбцы одномерных массивов
    for( i = 0; i < str; i++ )
        a[i] = new double*[row];
    
        // резервирование памяти под фактические данные матрицы
        for( i = 0; i < str; i++ )
          for( j = 0; j < row; ++j )
            a[i][j]  = new double;

Соответственно пишу:
Код

#include <iostream>
#include <iomanip>
using namespace std;

int main(void)
{    
    int str = 3, row = 3, tdim = 3;
    double ***a;
    int i, j, k;

    /* ВЫДЕЛЕНИЕ ПАМЯТИ ДЛЯ МАТРИЦЫ */
    // резервирование памяти под указатели на строки матрицы
    a = new double**[str];

    // резервирование памяти под указатели на столбцы одномерных массивов
    for( i = 0; i < str * row; i++ )
        *(a + i) = new double*[row];

    // резервирование памяти под фактические данные матрицы
    for( i = 0; i < str; i++ )
        for( j = 0; j < row; ++j )
            a[i][j]  = new double;
    
    /* ИНИЦИАЛИЗАЦИЯ МАТРИЦЫ */
    for( i = 0; i < str; i++ )
        for( j = 0; j < row; j++ )
            for( k = 0; k < tdim; k++ )
                ***(a + i + j + k ) = rand() % 100;

    /* ПЕЧАТЬ МАТРИЦЫ */
    for( i = 0; i < str; i++)
    {
        for( j = 0; j < row; j++ )
            for( k = 0; k < tdim; k++ )
                cout << setw(4) << ***(a + i + j + k );
            cout << endl;
        cout << endl;
    }

    /* ОСВОБОЖДЕНИЕ ПАМЯТИ, ВЫДЕЛЕННОЙ ДЛЯ МАТРИЦЫ */
    for( i = 0; i < str * row; i++ )
        // освобождение памяти, выделенной под фактические данные матрицы
        delete[] **(a + i);

    for( i = 0; i < str; i++ )
        // освобождение памяти, выделенной под указатели на столбцы одномерных массивов
        delete[] *(a + i);

    // освобождение памяти, выделенной под указатели на строки матрицы
    delete[] a;

    return 0;
}

Unhandled exception... Access violation writing location... при инициализации  в строке  smile 
Код

***(a + i + j + k ) = rand() % 100;

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


Опытный
**


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

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



бросай указатели
Код

#include <iostream>
#include <iomanip>
//#include <stdlib.h>

using namespace std;

int main(void)
{    
    int str=3, tdim=3,   all=3, col=3, row=3;
    double ***a;
    int i, j, k;

    /* ВЫДЕЛЕНИЕ ПАМЯТИ ДЛЯ МАТРИЦЫ */
    // резервирование памяти под указатели на строки матрицы
    a=new double**[ all ];
    
    // резервирование памяти под указатели на столбцы одномерных массивов
    for( i=0; i<col; i++ )
    {
        a[ i ] = new double*[ col];

        for( j=0; j<row; j++ )
            a[ i ][ j ]=new double[ row ]; 
        }

        /* ИНИЦИАЛИЗАЦИЯ МАТРИЦЫ */
        for( k=0; k<all; k++ )
            for( i=0; i<col; i++ )
                for( j = 0; j<row; j++ )
                    a[ k ][ i ][ j ]=rand() % 100;

        /* ПЕЧАТЬ МАТРИЦЫ */
        for( k=0; k<all; k++ )
        {
            for( i=0; i<col; i++ )
            {
                for( j=0; j<row; j++ )
                    cout << setw(4) << a[ k ][ i ][ j ];
                cout << endl;
                }
            cout << endl;
            }


// ОСВОБОЖДЕНИЕ ПАМЯТИ, ВЫДЕЛЕННОЙ ДЛЯ МАТРИЦЫ

for( i=0; i<all; i++ )
{
    for( j=0; j<col; j++ )
        delete [] a[ i ][ j ];
    delete [] a[ i ];
    }
delete[] a;

return 0;
}



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


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


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

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



Цитата(FiMa1 @  25.4.2007,  15:21 Найти цитируемый пост)
***(a + i + j + k ) = rand() % 100;

Так нельзя!

a[i][j][k] !=***(a + i + j + k ) 

Так что действительно бросай использовать указательную арифметику там, где она не нужна.

Добавлено через 2 минуты и 38 секунд
Цитата(Anikmar @  25.4.2007,  15:20 Найти цитируемый пост)
// Создание массива
    aMas = new double**[Size0];
    for (i=0;i<Size0;i++)
    {
        aMas[i] = new double* [Size1];
        for(j=0;j<Size1;j++)
            aMas[i][j] = new double[Size2];
    }


Чем отличается от моего варианта? Правда, у меня только создание, остальное тоже надо править.
Если ты имел в виду, что я не написал исправления остального кода, тогда да.






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


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

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



Даааа ) Прочёл весь топик от начала до конца )
Интересные вещи начитал ) и даже несколько утверждений себе на заметку взял)
Истина рождаеццо в споре, как говорят)


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Anikmar
Дата 26.4.2007, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



JackYF
Ваш код:
Код

 a = new double**[str]; 

 Это мы выделили память под str двухмерных массивов
Код

    // резервирование памяти под указатели на столбцы одномерных массивов
    for( i = 0; i < str; i++ )
        a[i] = new double*[row];

Это мы выделили память под массив указателей на строки двумерного массива (создали столбец) - Или создали строку с указаетлями на столбцы (как кто рассматривает)
Код

        // резервирование памяти под фактические данные матрицы
        for( i = 0; i < str; i++ )
          for( j = 0; j < row; ++j )
            a[i][j]  = new double;

А вот дальше я не понял. У нас есть только указатели. И сы создаем по одному элементу. А где используется третья размерность? В примере она tdim. Я ее не увидел. Получается по 3-му измерению у вас создается только 1 элемент. 

Цитата(JackYF @  25.4.2007,  16:42 Найти цитируемый пост)
Чем отличается от моего варианта? 

У меня эта часть сделана так:
Код

        aMas[i] = new double* [Size1];
        for(j=0;j<Size1;j++)
            aMas[i][j] = new double[Size2];

Третье измерение - у меня Size2. 

Это сообщение отредактировал(а) Anikmar - 26.4.2007, 09:05
PM MAIL ICQ   Вверх
FiMa1
Дата 26.4.2007, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(JackYF @ 25.4.2007,  16:42)
Цитата(FiMa1 @  25.4.2007,  15:21 Найти цитируемый пост)
***(a + i + j + k ) = rand() % 100;

Так нельзя!
a[i][j][k] !=***(a + i + j + k )
Так что действительно бросай использовать указательную арифметику там, где она не нужна.

Всем привет!

Друзья, торжественно клянусь никогда не использовать (да и не собирался) указательную арифметику для подобного запутывания кода! Однако, следует заметить, что данной код писался исключительно в целях изучения процедур доступа к i-му элементу многомерного массива посредством указателей (с этим у меня затруднения).
Посему, пожалуйста, ответьте на следующие мои вопросы:
Есть массив int array[i][j][k];
1. Как ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ записать в элемент [0][1][2] массива array значение, к примеру, 100?
2. Как ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ прочитать значение элемента [0][1][2] массива array?

Отдельное СПАСИБО тому, кто отважится закрепить ответы написанием программы динамического размещения массива array[][][] ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ и его инициализации ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ (не забудьте удалить массив ;).

PS: Думаю, это можно будет считать хорошим логическим завершением теоритических изысканий топика.
PM   Вверх
Anikmar
Дата 26.4.2007, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(FiMa1 @  26.4.2007,  11:58 Найти цитируемый пост)
Отдельное СПАСИБО тому, кто отважится закрепить ответы написанием программы динамического размещения массива array[][][] ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ и его инициализации ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ (не забудьте удалить массив ;).


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

Цитата(FiMa1 @  26.4.2007,  11:58 Найти цитируемый пост)
1. Как ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ записать в элемент [0][1][2] массива array значение, к примеру, 100?

Код

// Объявляем массив
int ***p;

// Выделяем под него память (см. выше)

// Присваиваем значение
p[0][1][2] = 20;

// Удаляем массив (см. выше)


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


Опытный
**


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

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



Цитата(Anikmar @ 26.4.2007,  12:56)
Не понял. Мой пример и создает и выводит и удаляет - и все только через указатели. Чем не устраивает?
Цитата(FiMa1 @  26.4.2007,  11:58 Найти цитируемый пост)
1. Как ПОСРЕДСТВОМ УКАЗАТЕЛЕЙ записать в элемент [0][1][2] массива array значение, к примеру, 100?

Код

// Объявляем массив
int ***p;
// Выделяем под него память (см. выше)
// Присваиваем значение
p[0][1][2] = 20;
// Удаляем массив (см. выше)

Да через указатели, но не "явно"...
Пусть есть одномерный массив int a[3]; тогда доступ к третьему (фактически второму, нумерация с нуля) элементу массива при явной записи с использованием указателей будет выглядеть как:
Код
int main(void)
{
    int a[3] = { 0, 1, 2 };

    //получаем третий эл-т с ПОМОЩЬЮ УКАЗАТЕЛЕЙ
    int thirdElem = *(a + 2);//thirdElem = 2
    //или явно, БЕЗ указателей
    thirdElem = a[2];
}

Как проделать тоже самое с трехмерным массивом array[][][] ?

Добавлено @ 13:30
Цитата(FiMa1 @ 26.4.2007,  13:19)
Как проделать тоже самое с трехмерным массивом array[][][] ?

Народ, так что ли правильно?

Код

int main(void)
{
    int a[3][3][3] = { { { 111, 112, 113 }, { 121, 122, 123 }, { 131, 132, 133 } },
                       { { 211, 212, 213 }, { 221, 222, 223 }, { 231, 232, 233 } },
                       { { 311, 312, 313 }, { 321, 322, 323 }, { 331, 332, 333 } } };

    int thirdElem = *(*(*(a + 0) + 1) + 2);
}


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


Опытный
**


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

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



FiMa1, не так.
Для первого раза можно так
Код

#define N1 4
#define N2 5
#define N3 6
//      const int N1=4,N2=5,N3=6; //Для C++ лучше не через define а так
      int A[N1][N2][N3];
      int *p = (int *)A;
      int i=1,j=2,k=3;
      A[i][j][k]=123;
      p[(i*N1+j)*N2+k]=321;

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

Добавлено через 6 минут и 56 секунд
Ну вот, и сам ошибся, надо
 
Код

    p[(i*N2+j)*N3+k]=321;

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


Опытный
**


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

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



Цитата
На эту тему есть много хороших книг.

Название книги в студию, пли-и-и-з. Правда сам не нашел именно про это нигде, уж извините...
Цитата
Если очень нужно, могу попробовать написать для тебя небольшое пояснение, но только позже

Спасибо, буду ждать!
PM   Вверх
apook
Дата 26.4.2007, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Код

#include<stdio.h>
#include<conio.h>

int main(void)
{
    int a[3][3][3] = { { { 111, 112, 113 }, { 121, 122, 123 }, { 131, 132, 133 } },
                       { { 211, 212, 213 }, { 221, 222, 223 }, { 231, 232, 233 } },
                       { { 311, 312, 313 }, { 321, 322, 323 }, { 331, 332, 333 } } };

int i, j, c;

for( i=0; i<3; i++ )
{
    for( j=0; j<3; j++ )
    {
        for( c=0; c<3; c++ )
            printf( " %d", *(*(*(a+i)+j)+c) );
        printf( "\t" );
        }
    printf( "\n" );
    }

getch();
}



Код

      A[i][j][k]=123;
      p[(i*N1+j)*N2+k]=321;

Ln78 Это что-то в натуре интересное, подозреваю что ты еще один запутыватель
ты не преподавателем работаешь нет... а то похоже


Это сообщение отредактировал(а) apook - 26.4.2007, 14:24


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


Эксперт
****


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

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



FiMa1, Имейте в виду

Вариант Ln78 только для массива, занимающего единый блок памяти (только для статики).
Вариант apook универсальный - сработает и на статическом масиве и на динамическом. - Я бы выбрал его.

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


Опытный
**


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

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



Цитата(apook @ 26.4.2007,  14:12)
Код

...
            printf( " %d", *(*(*(a+i)+j)+c) );
...

Так я, кажется, тоже самое написал в строке:
Код
int thirdElem = *(*(*(a + 0) + 1) + 2);

apook, получается Ln78 меня не правильно поправил?

PS: to apook: а как С ПОМОЩЬЮ УКАЗАТЕЛЕЙ динамически разместить данный массив в памяти и, С ПОМОЩЬЮ УКАЗАТЕЛЕЙ, реализовать инициализацию не показал (ну и удаление массива само собой). Просвяти, плз. Заранее спасибо!
PM   Вверх
JackYF
Дата 26.4.2007, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(FiMa1 @  26.4.2007,  13:19 Найти цитируемый пост)
int thirdElem = *(*(*(a + 0) + 1) + 2);

Кажись, да.

Цитата(Anikmar @  26.4.2007,  09:04 Найти цитируемый пост)
А вот дальше я не понял. У нас есть только указатели. И сы создаем по одному элементу. А где используется третья размерность? В примере она tdim. Я ее не увидел. Получается по 3-му измерению у вас создается только 1 элемент. 


Все, понял, где я недописал... да, тогда действительно была ошибка.



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


Опытный
**


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

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



Цитата

apook, получается Ln78 меня не правильно поправил?

Дело в том что он не поправил, а привел пример абсолютно не пвносящий ясность в твой вопрос, а где то даже наоборот.
Цитата

а как С ПОМОЩЬЮ УКАЗАТЕЛЕЙ динамически разместить данный массив в памяти и, С ПОМОЩЬЮ УКАЗАТЕЛЕЙ, реализовать инициализацию

Дело в том что я сам нахожусь в стадии изучения Cи пл пл и поэтому терпеть не могу вопиющие случаи запутывания мозгов интригующе
выглядещями примерами, в коих после долгого разбирательства обнаруживается минимум смысла(хорошо если правильного).

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

Если a[0] это *(a) то a[0][0] это *(*(a)) ну и т.д
Короче от простого пляшем, от простого к сложному как сказал кто-то, ведь знал же что говорил....


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


666
**


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

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



Цитата(apook @  26.4.2007,  16:13 Найти цитируемый пост)
Дело в том что он не поправил, а привел пример абсолютно не пвносящий ясность в твой вопрос, а где то даже наоборот.

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

Цитата(Ln78 @  26.4.2007,  14:50 Найти цитируемый пост)
      
Код

A[i][j][k]=123;      p[(i*N1+j)*N2+k]=321;

а вот здесь действительно что-то напутано

Это сообщение отредактировал(а) likehood - 26.4.2007, 15:24
PM MAIL   Вверх
Anikmar
Дата 26.4.2007, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(FiMa1 @  26.4.2007,  13:19 Найти цитируемый пост)
Да через указатели, но не "явно"...
Пусть есть одномерный массив int a[3]; тогда доступ к третьему (фактически второму, нумерация с нуля) элементу массива при явной записи с использованием указателей будет выглядеть как:


Цитата(FiMa1 @  26.4.2007,  14:28 Найти цитируемый пост)
PS: to apook: а как С ПОМОЩЬЮ УКАЗАТЕЛЕЙ динамически разместить данный массив в памяти и, С ПОМОЩЬЮ УКАЗАТЕЛЕЙ, реализовать инициализацию не показал (ну и удаление массива само собой). Просвяти, плз. Заранее спасибо! 


Так вы определитесь пожалуйста.
Чем мой пример вам не подходит?
Создание трехмерного массива - есть
Присвоение элементам через указатели - есть
Удаление - есть

А если вы определяете массив статически, то как тогда вы планируете его еще раз создать? И как уничтожить? 
Если он статический - он уже создан и он сам уничтожется при выходе из программы.
PM MAIL ICQ   Вверх
apook
Дата 26.4.2007, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



likehood
Компилятор встретив a[1] делает следующее *(a+1) стало быть так этот код работает на самом деле
Способ с указателями я привел только потому что Fima1 с самого начала на этом настаивает(читай предыдущие посты)
И отнють не говорю что это вносящий ясность способ.


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


Опытный
**


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

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



Цитата(Anikmar @ 26.4.2007,  16:00)
Так вы определитесь пожалуйста.
Чем мой пример вам не подходит?
Создание трехмерного массива - есть
Присвоение элементам через указатели - есть
Удаление - есть

Anikmar, Ваш вариант инициализации массива:
Код
// Заполнение элементами
for (i=0;i<Size0;i++)
    for(j=0;j<Size1;j++)
        for(k=0;k<Size2;k++)
            aMas[i][j][k] = rand() % 100;

Вариант инициализации с разыменованием через указатели:
for (i=0;i<Size0;i++)
    for(j=0;j<Size1;j++)
        for(k=0;k<Size2;k++)
            aMas[i][j][k] = *(*(*(a + i) + j) + k);[/code]
Разница понятна? По-моему мы разговариваем на разных языках...
Но, вообще, по мнению большинства, этот изврат не нужен, и, видимо, пора прикрывать дискуссии...
PM   Вверх
likehood
Дата 26.4.2007, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



Цитата(apook @  26.4.2007,  17:08 Найти цитируемый пост)
Компилятор встретив a[1] делает следующее *(a+1) стало быть так этот код работает на самом деле

Для одномерного массива все верно. Спор то с того и начался, что если размрность массива больше 1, компилятор все равно делает только одно разименование.
PM MAIL   Вверх
Anikmar
Дата 26.4.2007, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(FiMa1 @  26.4.2007,  14:28 Найти цитируемый пост)
PS: to apook: а как С ПОМОЩЬЮ УКАЗАТЕЛЕЙ динамически разместить данный массив в памяти и, С ПОМОЩЬЮ УКАЗАТЕЛЕЙ, реализовать инициализацию не показал (ну и удаление массива само собой). Просвяти, плз. Заранее спасибо! 

Указатели вам подсказал apook
Как создавать массив и его удаляеть - есть в моем коде
Остается поменять индексный доступ на указатели - и все есть

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

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


Опытный
**


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

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



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

Смотри сюда
PM MAIL   Вверх
apook
Дата 26.4.2007, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



В догоночку, для ясности smile
Код

#include<stdio.h>
#include<conio.h>

int main(void)
{
int i, j, c;
int a[ 3 ][ 3 ][ 3 ] = { {{111, 112, 113}, {121, 122, 123}, {131, 132, 133}},
                         {{211, 212, 213}, {221, 222, 223}, {231, 232, 233}},
                         {{311, 312, 313}, {321, 322, 323}, {331, 332, 333}} };


int *b;

b=&a[ 0 ][ 0 ][ 0 ];

for( i=0; i<3; i++ )
{
    for( j=0; j<3; j++ )
    {
        for( c=0; c<3; c++ )
            printf( " %d", *b++ );
        printf( "\t" );
        }
    printf( "\n" );
    }

getch();
}


Цитата

Смотри сюда

Ну и че ты это сюда сунул что там о чем то похожем говорили?
До фига мозги что-ли включены...


Это сообщение отредактировал(а) apook - 26.4.2007, 18:09


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


Эксперт
****


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

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



Цитата(apook @  26.4.2007,  18:01 Найти цитируемый пост)
В догоночку, для ясности 

Для ясности чего?
PM MAIL ICQ   Вверх
apook
Дата 26.4.2007, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



для ясности в кавычках "" не видиш смайлик улыбающийся


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


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Ы-ы-ыы, машину разбил. Вернее три машины. Сначала одному задом въехал на заправке, а потом другому в зад заехал на светофоре. Хорошо хоть страховка есть.  Ладно, переживём. smile

Цитата(Fazil6 @  25.4.2007,  08:57 Найти цитируемый пост)
Ты же все время утверждал, что имя двумерного массива является int**

Я и сейчас это утверждаю. А где ты увидел противоречие? Да, я это говорил, не отрицаю. И буду говорить. А ещё я говорил, что тип  int** это ни что иное, как указатель на указатель на  int. Говорил??? Говорил. И что такое указатель на указатель на  int тоже говорил. Могу ещё раз повторить. Это значит, что его значением может быть только адрес. Причём не просто какой-то адрес, а именно адрес указателя на int, т.е. такого указателя, который имеет тип int*. 
Цитата(Fazil6 @  25.4.2007,  08:57 Найти цитируемый пост)
Теперь это у тебя адрес двумерного массива. То есть, грубо говоря, int***
Да пойми ты, наконец, что имя массива и его адрес это совершенно разные вещи. Вот смотри. Покажу тебе на простом примере. Берём двумерный массив А[3][3].В этом массиве есть, как не трудно подсчитать, 9 элементов, имеющих тип int. Но адреса каждого из этих элементов &А[0][0], &А[0][1], &А[0][2]... и т.д. имеют тип int*. Почему? Потому, что являются указателями на тип int. Опять же, почему? Потому, что в С/С++ понятие указатель имеет не только переменная, объявленная, как указатель, напр. int* р; , но и значение этого указателя, напр. &А[0][1] или &var, находящееся справа от знака присваивания. Если в выражении int a = 5 + 2; и переменная а и результат вычисления 5 + 2 имеют тип int, т.е. целые числа, то в выражении int* p = &А[0][0]; и переменная р и результат вычисления &А[0][0] имеют тип int*, т.е. указатели на int. Ну, это хоть понятно? 
Имя одномерного массива А[0], который является подмассивом двумерного массива А[3][3] является указателем потому, что хранит адрес первого элемента А[0][0]. Поэтому имя подмассива А[0] имеет тип int*, точно так же, как и &А[0][0]
Но ведь подмассив А[0] сам является первым элементом массива А. Имя массива А, в свою очередь, является указателем потому, что хранит адрес первого элемента, т.е. подмассива А[0]. И если имя подмассива А[0] имеет тип int*, то его адрес имеет тип  int**, так как является указателем на указатель на  int. Вот и получается, что имя массива А имеет тип int** и является указателем на указатель на int. Почему, опять же? Да всё потому же, ёлы-палы. Потому что адрес его первого элемента это указатель на указатель на int, имеющий тип  int**. Это понятно? 
Что же мы имеем? Смотрите внимательно. Показываю последний раз. Больше повторять не буду.  smile 
Если объект(или его имя, или переменная, не важно) имеет тип  int, то его адрес имеет тип  int*.
Если объект имеет тип  int*, то его адрес имеет тип  int**.
Если объект имеет тип  int**, то его адрес имеет тип  int***...
И так до... Не знаю сколько, но очень долго.
 
Теперь мы видим, что если имя массива имеет тип int**, то его адрес имеет тип  int***. Вот почему я говорил, что адрес двумерного массива имеет тип int***. Но это в том примере не главное. Я хотел сказать другое.  Имя массива не потому указатель, что его можно или нельзя присвоить какому-нибудь указателю(указатель не этим определяется), а просто потому, что оно хранит адрес.  И последнее. Разыменование указателя, т.е. получение значения с адреса можно применить только к указателям. И если это можно проделать с именем массива, то почему его нельзя считать указателем? 
Опять же, это моё мнение. И я его высказываю, и пытаюсь объяснить свою точку зрения. В ответ же слышу только одно. Dov, ты не прав. Ну, допустим я не прав. Ну пусть тогда мне хоть один знаток стандарта объяснит, почему самолёты летают, а крыльями не машут. То есть, почему он пользуется именем массива, как указателем, когда разыменовывает его и получает доступ к значениям, а называть его указателем не хочет. Это я не про индексы говорю, а про звёздочки... 
Да, впрочем, ничего мне говорить не нужно.  Я уже вижу руки, тянущиеся к клавиатуре, что бы напечатать три слова. Dov, ты не прав.

Ладно, развлекайтесь тут без меня. Пойду лучше FiMa1`е помогу.
 
FiMa1, вариант Anikmar`а, тот что с индексами, очень хороший. Если есть проблемы с пониманием работы указателей, то лучше, с моей точки зрения, использовать его.  Но я так понимаю, что ты просто хочешь потренироваться  в использовании указателей. 

Цитата(Anikmar @  26.4.2007,  17:07 Найти цитируемый пост)
Остается поменять индексный доступ на указатели - и все есть
Это правильно. Так и нужно сделать. 
Вот тебе переделаный вариант Anikmar`а.
Код
int main(void)
{
    srand((unsigned)time(NULL));

    int str = 3, row = 5, tdim = 4;
    double ***a;
    int i, j, k;
    
    a = new double**[str];    

    for(i = 0; i < str; i++)
    { 
        *(a + i) = new double* [row];
        for(j = 0; j < row; j++)
            *(*(a + i) + j) = new double[tdim];
    } 
    
    for(i = 0; i < str; i++)
        for(j = 0; j < row; j++)
            for(k = 0; k < tdim; k++)
                *(*(*(a + i) + j) + k) = rand() % 100;
            
    for(i = 0; i < str; i++)
    {
        for(j = 0; j < row; j++)
        {
            for(k = 0; k < tdim; k++)
                cout << setw(4) << *(*(*(a + i) + j) + k);
            cout << endl;
        }
        cout << endl;
    }
            
    for(i = 0; i < str; i++)
    {
        for(j = 0; j < row; j++)
            delete [] *(*(a + i) + j);
        delete [] *(a + i);
    }
            
    delete[] a;
            
    return 0;
}
 

Цитата(Anikmar @  26.4.2007,  14:26 Найти цитируемый пост)
FiMa1, Имейте в видуВариант Ln78 только для массива, занимающего единый блок памяти (только для статики).

А что нам может помешать создать динамический массив?   smile Кстати, и печатать раза в два меньше прийдётся. И выделение/освобождение памяти попроще будет. 
Код
int main(void)
{
    srand((unsigned)time(NULL));
    int     str = 3, row = 5, tdim = 4;    
    double *a, val;

    a = new double[str * row * tdim]; 

    for( int i = 0; i < str; i++)
    {
        for(int j = 0; j < row; j++)
        {
            for(int k = 0; k < tdim; k++)
            {
                val = *(a + (i * row * tdim) + (j * tdim) + k) = rand() % 100;
                cout << setw(4) << val;
            }
            cout << endl;
        }
        cout << endl;
    } 
    delete[] a;

    return 0;
}


Так, вроде всё. Всем пока.  smile 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Ln78
Дата 27.4.2007, 06:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



FiMa1 и все желающие, первую часть статьи (случай статического распределения памяти) написал, можешь посмотреть. 
Dov, сочувтвия по поводу машин. В своём опусе, по странному стечению обстоятельств, я упоминал и тебя, и гаишников. Надеюсь, что в аварии я всё-таки не виноват smile 

Присоединённый файл ( Кол-во скачиваний: 34 )
Присоединённый файл  Comment.rar 21,09 Kb
PM MAIL   Вверх
apook
Дата 27.4.2007, 08:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Во бл.. поэия!  Ln78 Не ожидал от тебя такого. еще бы в стихотворной форме че полинился? А вообще наверно познавательно но длинно, я устал читать.



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


Эксперт
****


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

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



Цитата(Dov @  27.4.2007,  03:32 Найти цитируемый пост)
Цитата(Anikmar @  26.4.2007,  14:26 )
FiMa1, Имейте в видуВариант Ln78 только для массива, занимающего единый блок памяти (только для статики).


А что нам может помешать создать динамический массив?    Кстати, и печатать раза в два меньше прийдётся. И выделение/освобождение памяти попроще будет. 


Я имел в виду ограниченность применения приведенного примера в том, что там априоре предполагается размещение массива в едином блоке памяти:

Цитата(Ln78 @  26.4.2007,  13:50 Найти цитируемый пост)
 
      int A[N1][N2][N3];
      int *p = (int *)A;
      int i=1,j=2,k=3;
      A[i][j][k]=123;
      p[(i*N1+j)*N2+k]=321;


Примененный метод адресации по сути использует только указатель на базовый адрес: p[(i*N1+j)*N2+k]=321;,  при универсальной работе - нужно применять разименование: *(*(*(a + i) + j) + k)

Вот поэтому, я и написал, что вариант Ln78 будет работать, если массив объявлен статически либо единым блоком памяти (в последнем случае нельзя будет применить скобки, а только метод вычисления смещения)

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

Мне кажется, путаница в данной теме возникла именно из-за того, что многие уверены, что массив должен занимать единый блок памяти и его адрес является адресом первого элемента массива. Во многих случаях это так, но единого блока памяти может и не быть, поэтому вычисление смещения элемента путем прибавления какого-то числа к базовому адресу заведомо ошибочно и работает только в ограниченных случаях.
Разыменование вида *(*(*(a + i) + j) + k) работает при любом способе объявления и организации массива - и статического (когда это действительно один большой блок памяти) и динамического - когда подмасивы могут находится где угодно.
PM MAIL ICQ   Вверх
apook
Дата 27.4.2007, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

массив должен занимать единый блок памяти

Цитата

Во многих случаях это так, но единого блока памяти может и не быть,

Статический массив (если он полностью статический) всегда будет занимать единый блок помяти...


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


Эксперт
****


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

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



Цитата(apook @  27.4.2007,  09:38 Найти цитируемый пост)
Статический массив (если он полностью статический) всегда будет занимать единый блок помяти... 


А я как сказал? Именно это я и подразумевал как само собой разумеющееся:

Цитата(Anikmar @  27.4.2007,  09:17 Найти цитируемый пост)
если массив объявлен статически либо единым блоком памяти 


Хотя конечно это на сегодняшний день это так, может появится какой-нить чудо-компилятор, который и статические массивы будет распихивать по дыркам в памяти - кто знает.  smile  
Интересно, а если я объявлю достаточно громадный статический массив, для которого будет нехватать единого блока памяти. Программа не запустится? Или линкер ругнется? Лень проверять.
PM MAIL ICQ   Вверх
Fazil6
Дата 27.4.2007, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Dov @  27.4.2007,  03:32 Найти цитируемый пост)
Да пойми ты, наконец, что имя массива и его адрес это совершенно разные вещи.

и где я сказал, что это одно и тоже? Это ты сказал?
Цитата(Dov @  24.4.2007,  23:43 Найти цитируемый пост)

int p[3][3];
int** pAr = p;
Ты хоть понимаешь, что ты здесь написал. Ты пытаешься указателю на указатель на инт присвоить адрес двумерного массива

хотя до этого утверждал, что  имя двумерного массива это указатель на указатель, т.е. int** и вдруг оно уже int***. p это имя двумерного массива. 

Цитата(Dov @  27.4.2007,  03:32 Найти цитируемый пост)
И последнее. Разыменование указателя, т.е. получение значения с адреса можно применить только к указателям. И если это можно проделать с именем массива, то почему его нельзя считать указателем?

никто не говорит, что имя массива нельзя использовать как указатель, только вот указатель на что...
не думай, что если можно написать
Цитата

int a = **p;

то из этого можно сделать вывод, что p это int**. Первое разыменовывание возвращает int[3] , а второе int. 
ты ведь не станешь утверждать, что здесь
Код

class A 
{
public:
    operator int(){return x;}
private:
    const static int x = 100;
};

int main()
{
    A a;
    A *pa = &a;
        A **ppa = &pa;

    int x = *pa;
         int y = **ppa;
    std::cout << x << "    " << y;
return 0;
}

pa это int* или ppa - это int**... Или pa это int* ?

вот тебе пример

Код

void f(int *m)
{
    std::cout << "f output " << *m << "\n" ;
}

void pf(int **m)
{
    std::cout << "pf output " << **m << "\n" ;
}


int x[2] = {1,2};
int *px = x;  // вполне законно. x используется как int* 
                   // и совсем не как указатель на массив и , опятьже по твоему, грубо говоря int**

// и вот это работает
std::cout << px[0] << "\n";
// и вот это
std::cout << px[1] << "\n";
// и даже вот так
std::cout << *(px + 1) << "==" << x[1] << "==" <<  *(x + 1) << "\n";
// и даже в функцию можно передать
f(x);
// везде где нужно x используется как int*


// и всю эту аналогию ты переносишь на многомерные масивы
int y[2][2] = {{3,4}, {5,6}};
// y - это имя двумерного массива интов, и по твоему имеет тип int**

int **py = y // почему нельзя сделать так? одному int** присвоить значение другого int**
// почему это прокатывало с одномерным массивом? 

//почему y(имя двумерного массива, по твоему типа int**) нельзя передать 
//в функцию принимающую int** ???
pf(y); 

// y - можно использовать как указатель и с этим никто не спорит, но не как указатель на указатель на int

// я заметил, что ты очень любишь приведение типа 
std::cout << **((int **)y);  
// здесь говорится что y(имя массива) должен использоваться как int** хотя он и так по твоему типа int**
// и приведение вообще лишнее и ничего не должно менять. 
// но имеем чпок!!!

//Был правда разговор, что y это вообще int***,
// но эту чушь не фурычит аналогично


// Вопрос : почему такие проблемы с y(использованием как указатель на указатель на int)
// Ответ : потому, что y(имя массива) не int**




с удовольствием ознакомлюсь с примером использования двумерного массива или его имени в качестве int**. Вполне сойдет ссылка на приводимые ранее примеры или свежачек какой-нить...


Цитата(Dov @  27.4.2007,  03:32 Найти цитируемый пост)
Имя массива не потому указатель, что его можно или нельзя присвоить какому-нибудь указателю(указатель не этим определяется), а просто потому, что оно хранит адрес.
повторяю, никто не говорит, что это не указатель, все говорят тебе, что ты совершенно неправильно понимаешь на что этот указатель указывает, причем с наездами непонимаешь. 
Имя двумерного массива содержит адрес инта, до значения которого можно добраться [0][0].   Т.е. по адресу, который асоциирован с именем двумерного массива лежит int. Так почему бы на основании этого не сделать вывод, что имя двумерного массива является типом int* ??? Много всякой чепухи можно напридумывать....

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


Опытный
**


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

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



Цитата(Ln78 @ 27.4.2007,  06:24)
FiMa1 и все желающие, первую часть статьи (случай статического распределения памяти) написал, можешь посмотреть.

Зачотная статья, имхо! Молодец! Остаток статьи, после "Он говорит про себя «Ужо тебе, озорник»" дочитывал ПАДСТАЛОМ... Небольшая очепятка на 2-й странице "И тип int, мы договорились считать тоже 4-х битным". В целом все написано доходчивым языком.
Обязательно буду ждать серии второй.
PM   Вверх
Anikmar
Дата 27.4.2007, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  27.4.2007,  10:09 Найти цитируемый пост)
с удовольствием ознакомлюсь с примером использования двумерного массива или его имени в качестве int**. Вполне сойдет ссылка на приводимые ранее примеры или свежачек какой-нить...


Для краткости: говорим о двухмерных массивах.

Это нельзя. Имя массива, хоть и приводится спокойно к **, но дальше компилятор ничего не знает о размерности массива.
Когда компилятор встречает конструкцию вида:
Код

int **p;
p[1][2] = 15;

То он подразумевает, что в p[1] находится указатель на массив интов. В соответствии с этим, если мы напишем конструкцию:
Код

int a[3][4];
int **P;

p = (int**)a;
p[1][2] = 15;


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

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

void main(void )
{
    int a[3][4] = {{100,101,102,103},{110,111,112,113},{120,121,122,123}};
    int **pp;
    int i,j;

    pp = new int*[3];
    pp[0] = a[0];
    pp[1] = a[1];
    pp[2] = a[2];

/*
   После этого работаем с pp как будто это a
*/
    for (i=0;i<3;i++)
        {
            for(j=0;j<4;j++)
            {
                printf("%d\t",pp[i][j]);
                pp[i][j]*=2;
            }
            printf("\n");
        }
    printf("\n\n");
    for (i=0;i<3;i++)
        {
            for(j=0;j<4;j++) printf("%d\t",pp[i][j]);
            printf("\n");
        }

    getch();

}



Я только такой способ знаю статический массив привести к динамическому. Наверное есть и другие.
Конструкции вида *(p + RowCount*i+j) Я считаю медленными и громоздкими
PM MAIL ICQ   Вверх
JackYF
Дата 27.4.2007, 13:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Dov @  27.4.2007,  03:32 Найти цитируемый пост)
что имя массива и его адрес это совершенно разные вещи

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

Код

int p[10];
cout << p << '\n'; // имя массива
cout << &p; // его адрес


В обоих случаях буду выданы идентичные числа.

Жду возражений smile

Dov, ты не прав.


Цитата(Dov @  27.4.2007,  03:32 Найти цитируемый пост)
что бы напечатать три слова. Dov, ты не прав.

Да, кстати - здесь четыре слова smile



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


Шустрый
*


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

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



вот что говорит стандарт ISO/IEC14882 пункт 8.3.4.8
Цитата

[Example: consider
int x[3][5];
Here x is a 3×5 array of integers. When x appears in an expression, it is converted to a pointer to (the first of three) five-membered arrays of integers. In the expression x[i], which is equivalent to *(x+i), x is first converted to a pointer as described; then x+i is converted to the type of x, which involves multiplying i by the length of the object to which the pointer points, namely five integer objects. The results are added and indirection applied to yield an array (of five integers), which in turn is converted to a pointer to the first of the integers. If there is another subscript the same argument applies again; this time the result is an integer.
]

Dov ты все таки не прав...

Это сообщение отредактировал(а) _stranger_ - 27.4.2007, 13:50
PM MAIL   Вверх
Fazil6
Дата 27.4.2007, 13:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  12:51 Найти цитируемый пост)
Это нельзя. Имя массива, хоть и приводится спокойно к **

по вашему reinterpret_cast это спокойно приводится???  smile  С помощь этого Вы свой массив к чему угодно приведете

Код

class A
{
};

int a[3][4];

A *aa = reinterpret_cast<A*>(a);
A *aa = (A*)(a);
int *********** b = (int ***********)a;

// а как был int [3][4] так и остался



Цитата(Anikmar @  27.4.2007,  12:51 Найти цитируемый пост)
После этого работаем с pp как будто это a
 и что? вопрос в том как это использовать наоборот
Цитата

После этого работаем с a как будто это pp (т.е. int**)


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


Эксперт
****


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

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



Цитата(Fazil6 @  27.4.2007,  13:50 Найти цитируемый пост)
и что? вопрос в том как это использовать наоборот


В каком смысле? Запихать в него какие-то свои значения?
Я не понял слово "наоборот"


Цитата(Fazil6 @  27.4.2007,  13:50 Найти цитируемый пост)
по вашему reinterpret_cast это спокойно приводится???    С помощь этого Вы свой массив к чему угодно приведете


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

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

Имеем объявление
int a[3][4];
int **p;

Соответственно:
Конструкция p[0] должна вернуть указатель на int
Конструкция a[0] также вернет указатель на int

Какие конкретно действия "наоборот" вас интересуют?


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


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  15:16 Найти цитируемый пост)
Какие конкретно действия "наоборот" вас интересуют?

привести пример выражения где int a[3][4] использовался бы как int**. 
PM MAIL   Вверх
Anikmar
Дата 27.4.2007, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  27.4.2007,  15:42 Найти цитируемый пост)
привести пример выражения где int a[3][4] использовался бы как int**.  


Я такой пример привел, он вас не устроил? Например так:
Код

int a[3][4];
int **p;
int *d;

d = p[0];
d = a[0];


Добавлено через 5 минут и 52 секунды
Или так:
Код

    int a[3][4] = {{100,101,102,103},{110,111,112,113},{120,121,122,123}};
    int i;

    for (i=0;i<4;i++) printf("%d\t",*(*a)+i);
    printf("\n");


PM MAIL ICQ   Вверх
Fazil6
Дата 27.4.2007, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  15:58 Найти цитируемый пост)
Я такой пример привел, он вас не устроил? Например так:

хм... в какой строке массив или его имя используется именно как int**? Правда не вижу
PM MAIL   Вверх
Anikmar
Дата 27.4.2007, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Anikmar @  27.4.2007,  15:58 Найти цитируемый пост)
*(*a)+i


Как тогда вы эту строку расцениваете? Как работу с целым числом?

Добавлено через 1 минуту и 57 секунд
Объясните, какие действия вы хотите сделать с двойным указателем? Приведите пример работы с двойным указателем, который бы вы хотели увидеть?
PM MAIL ICQ   Вверх
Fazil6
Дата 27.4.2007, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  16:17 Найти цитируемый пост)
Как тогда вы эту строку расцениваете? Как работу с целым числом?

ну совсем не как int**, ведь если 2 раза разыменовать и в результате получить int еще не означает, что то, что разыменовывается имеет тип int**. Я привел пример когда **ppa выдает int, но ppa не является int** 

http://forum.vingrad.ru/index.php?showtopi...t&p=1114163
 
ведь получаемый результат выражения (я имею в виду адрес) a + 1 разный в зависимости от того какого типа a. Ведь если a типа int** , то смещение будет 4*1 байта, а если a[2][2] , то смещение будет sizeof(int[2])*1. 
и в твоем примере с циклом *a возвращает массив int[4] , а потом к нему применяется смещение 0 и разыменовывание дает int

Добавлено через 3 минуты и 9 секунд
Цитата(Anikmar @  27.4.2007,  16:17 Найти цитируемый пост)
Объясните, какие действия вы хотите сделать с двойным указателем? Приведите пример работы с двойным указателем, который бы вы хотели увидеть?

мне неизвестны такие примеры, которые компиллировались бы, либо компиллировались и работали бы. Поэтому я и утверждаю, что ни массив int a[2][2] ни его имя не являются int**. Те кто это утверждают, видимо знают такие действия и примеры
PM MAIL   Вверх
Anikmar
Дата 27.4.2007, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  27.4.2007,  16:31 Найти цитируемый пост)
ну совсем не как int**, ведь если 2 раза разыменовать и в результате получить int еще не означает, что то, что разыменовывается имеет тип int**. Я привел пример когда **ppa выдает int, но ppa не является int**

С такой логикой можно любой пример оспорить.

К этому коду это суждение не относится. Разыменовывается без всяких приведений и искусственных преобразований (переопределений) и выдает именно то значение, которое  ожидалось.


Цитата(Fazil6 @  27.4.2007,  16:31 Найти цитируемый пост)
ведь получаемый результат выражения (я имею в виду адрес) a + 1 разный в зависимости от того какого типа a. Ведь если a типа int** , то смещение будет 4*1 байта, а если a[2][2] , то смещение будет sizeof(int[2])*1. 
и в твоем примере с циклом *a возвращает массив int[4] , а потом к нему применяется смещение 0 и разыменовывание дает int


Если вы считаете, что этот результат случайный так, как размеры int и указателя совпадают попробуем по-другому:
Код

    double aa[3][4] = {{100.1,101.2,102.3,103.4},{110.1,111.2,112.3,113.4},
        {120.1,121.2,122.3,123.4}};

    for (i=0;i<4;i++) printf("%lf\t",*((*aa+1)+i));



Теперь выдаем 2-ю строку массива (или столбец - как кому удобнее)
Что теперь с указательной арифметикой не устроит?

Добавлено через 6 минут и 58 секунд
Цитата(Fazil6 @  27.4.2007,  16:31 Найти цитируемый пост)
мне неизвестны такие примеры, которые компиллировались бы, либо компиллировались и работали бы. Поэтому я и утверждаю, что ни массив int a[2][2] ни его имя не являются int**. Те кто это утверждают, видимо знают такие действия и примеры 


Я привел вам 2 работающих примера, когда имя массива можно использовать в качестве указателя. Я никогда не утверждал, что имя массива является указателем - так как он имеет тип int[3][4] - это легко увидеть использовав typeid(...).name()

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

Если бы вы не увидели предыдущего текста, как бы вы расценили эту строку:
printf("%lf\t",*((*aa+1)+i));

У вас бы спросили какого типа aa? Что бы вы ответили? По выражению - это работа с двойным указателем и никак иначе. Строка одинаково выглядит и если бы aa была бы объявлена как ** и как двойной массив.

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


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  16:43 Найти цитируемый пост)
У вас бы спросили какого типа aa? Что бы вы ответили? По выражению - это работа с двойным указателем и никак иначе. Строка одинаково выглядит и если бы aa была бы объявлена как ** и как двойной массив.

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

Цитата(Fazil6 @  27.4.2007,  16:31 Найти цитируемый пост)
ведь получаемый результат выражения (я имею в виду адрес) a + 1 разный в зависимости от того какого типа a. Ведь если a типа int** , то смещение будет 4*1 байта, а если a[2][2] , то смещение будет sizeof(int[2])*1. и в твоем примере с циклом *a возвращает массив int[4] , а потом к нему применяется смещение 0 и разыменовывание дает int
 и aa в твоем примере используется как указатель на массив , а не как double**

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


Эксперт
****


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

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



Цитата(Fazil6 @  27.4.2007,  17:46 Найти цитируемый пост)
и aa в твоем примере используется как указатель на массив , а не как double**


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

char *s; - Это указатель именно на переменную типа char (т.е. на 1 символ) или на массив таких символов? Ответьте мне, пожалуйста.

Далее:

char **s; - Это указатель на указатель на символ или указатель на массив указателей на символ?


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


Опытный
**


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

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



Это вообще указатель на массив указателей на тип char
и другое дело какие адреса взяты указателями



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


Эксперт
****


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

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



Цитата(apook @  27.4.2007,  17:56 Найти цитируемый пост)
Это вообще указатель на массив указателей на тип char

А просто как указатель на указатель его нельзя использовать? Можно.

Тогда объяснитем мне смысл этой фразы:

Цитата(Fazil6 @  27.4.2007,  17:46 Найти цитируемый пост)
и aa в твоем примере используется как указатель на массив , а не как double**


Как тогда использовать double**? Как указатель на массив не подходит, а как нужно?

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


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  17:51 Найти цитируемый пост)
т.е. согласно вашей логике, указатель на конкретный тип данных и указатель на массив из таких данных отличаются?

да. массив и указатель это разные типы. Передай sizeof массив и указатель , который указывает на его первый элемент. Получишь разные результаты. tipeid выдаст разное.  Физически - это адрес, но работа с ним и результат зависит от того как объявлено.
Цитата(Anikmar @  27.4.2007,  17:51 Найти цитируемый пост)
char *s; - Это указатель именно на переменную типа char (т.е. на 1 символ) или на массив таких символов? Ответьте мне, пожалуйста.

это указатель на символ. Массив символов при передаче в функцию передается как char *s.

Строковый литерал "11" имеет тип char[3].

Я понимаю, что соблазн представлять массив как указатель достаточно велика, но если следовать логике, что  в строке
for (i=0;i<4;i++) printf("%d\t",*(*a)+i); a - используется в виде int** , то почему в параметрах функции двумерный массив не преобразуется в int**.
Весь фокус не в том насколько велика разница между массивом и указателем, а в том что слишком большая разница между указателем на массив и указателем на указатель.
PM MAIL   Вверх
Anikmar
Дата 27.4.2007, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



P.S.

Цитата(apook @  27.4.2007,  17:56 Найти цитируемый пост)
Это вообще указатель на массив указателей на тип char


А я как написал? По-другому?

Цитата(Anikmar @  27.4.2007,  17:51 Найти цитируемый пост)
Это указатель на указатель на символ или указатель на массив указателей на символ?


Если конечно не придираться, что я char назвал символом - ну лень мне было язык переключать   smile 
PM MAIL ICQ   Вверх
Fazil6
Дата 27.4.2007, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Код

char *s = "1111";

допустимо только для совместимости со старым кодом.
так ведь недопустимо
Код

int *pi = {1,2,3};


Добавлено @ 18:10
Цитата(Anikmar @  27.4.2007,  17:51 Найти цитируемый пост)
char **s; - Это указатель на указатель на символ или указатель на массив указателей на символ?

это указатель на указатель на char или на символ, в данном случае понятно.


Это сообщение отредактировал(а) Fazil6 - 27.4.2007, 18:11
PM MAIL   Вверх
Anikmar
Дата 27.4.2007, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  27.4.2007,  18:04 Найти цитируемый пост)
то почему в параметрах функции двумерный массив не преобразуется в int

Потому, что он таковым не является.

Тут примерно такая же разница как между адресом функции и адресом метода класса.
Если массив определяется статически - то для вычисления смещения необходимо знать размерность этого массива. А в голом указателе такой информации нет.

Если вы создаете массив динамически и передаете его в функцию, то что должна знать функция? Это адрес собственно массива и его размерности. Для чего? Чтобы правильно вычислить местоположение конкретного элемента.

Когда массив определен явно, он выделяется прямым куском в памяти и размерности его известны. Именно поэтому он получает тип int [3][4], а не int** - т.е. в этот тип уже явно включены размерности.

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

Если мы создадим динамический массив единым куском, то он не будет двухмерным с точки зрения языка Си++ - вы не сможете доступиться к его элементам стандартным оператором [][]. Так как в этом большом куске будут отсутствовать  указатели, которые будет искать данный оператор.

А когда этот оператор пытается найти искомые указатели в статическом массиве - то ему на вход передается уже другой тип данных, не int**, а int[3][4] - соответственно адрес конкретного элемента вычисляется по-другому.

Нельзя передать в функцию статический двухмерный массив как указатель именно из-за разного алгоритма вычисления смещения элемента. Функция, которая получит на вход двойной указатель будет вызывать оператор [][], относящияся именно к двойному указателю, а не к int[3][4].  

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

Код

// Объявляем статический массив
int a[3][4] = {{100,101,102,103},{110,111,112,113},{120,121,122,123}};
// Объявляем двойной указатель
int *pp;

pp = (int**)a;
pp[0][1] = 100; // Так нельзя, компилятор ждет, что в pp[0] находится указатель, а его там нет - так как для статических массивов они не определяются.

// Но если сделать так:
pp = new int*[3];
pp[0] = a[2];
pp[1] = a[1];
pp[2] = a[0];

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

// теперь pp[0][0] == 120 и это абсолютно ожидаемый результат.



Цитата(Fazil6 @  27.4.2007,  18:04 Найти цитируемый пост)
Передай sizeof массив и указатель , который указывает на его первый элемент. Получишь разные результаты. tipeid выдаст разное.  Физически - это адрес, но работа с ним и результат зависит от того как объявлено.


Нет и еще раз нет.
Если мы объявим 
char *s; - то это всегда указатель
char s[30]; - это совсем другой тип, это явно заданный массив и имеет тип char[30]

char *s = new char[100];
char *ss;
// Это уже динамический массив. Причем и s и ss имеют одинаковый тип.

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

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

Добавлено @ 18:32
Цитата(Fazil6 @  27.4.2007,  18:08 Найти цитируемый пост)
допустимо только для совместимости со старым кодом.
так ведь недопустимо

код C++
1:

int *pi = {1,2,3};


Естественно недопустимо. В языке не определены константы адреса. И только из-за этого. Инициализировать можно только вещами, которые понимает компилятор. А в языке определены числовые константы, логические, а адресные - нет. Он их просто не знает.




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


Эксперт
****


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

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



Цитата(Anikmar @  27.4.2007,  19:29 Найти цитируемый пост)
В языке не определены константы адреса

Цитата(Anikmar @  27.4.2007,  19:29 Найти цитируемый пост)
А в языке определены числовые константы

а вчем различие?
Код

int* p = 234;

Это я не задал адрес?
PM MAIL WWW   Вверх
Anikmar
Дата 27.4.2007, 19:30 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Daevaorn @  27.4.2007,  19:16 Найти цитируемый пост)
Это я не задал адрес? 

Нет, это целое число.
Дело в том, что исторически сложилось, что адрес и int имеют одинаковый размер  - с точки зрения архитектуры процессора - все понятно.

Но адресных констант в языке нет, в ранних версиях я еще встречал описание причины - дескать язык высокого уровня не должен быть зависим от архитектуры машины, в современном стандарте даже упоминаний нет. В разделе константы - там есть целые числа, числа с плавающей точкой, строковые и символьные константы и служебные константы true и false. Больше нет. 

Да и посудите сами: допустим процессор motorola для видеоприставок. Был еще в конце 80-х годов. На тот момент intel был еще 16 разрядным, а motorola уже имела прямую 32-битную адресацию.
Ка должна выглядеть адресная константа? При всем при том, что на Си можно было писать и обработчики прерываний и драйверы. Тогда для семейства x86 она должна выглядеть как-то так: 000CC:000dd - т.е. сегмент + смещение, а для мотороловского процессора уже как 32 битное единое число без сегментации: как-то так. сссааа00 Причем int был все равно 16-разрядным.

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

И с появлением 64-разрядных систем в 32 разрядный int указатель уже не запихаешь. А не за горами 128 разрядные.
PM MAIL ICQ   Вверх
Daevaorn
Дата 27.4.2007, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Anikmar @  27.4.2007,  20:30 Найти цитируемый пост)
а должна выглядеть адресная константа? При всем при том, что на Си можно было писать и обработчики прерываний и драйверы. Тогда для семейства x86 она должна выглядеть как-то так: 000CC:000dd - т.е. сегмент + смещение, а для мотороловского процессора уже как 32 битное единое число без сегментации: как-то так. сссааа00

ну тут на самом деле вопрос интерпритации компилятором и процессором некого числа как адреса. хотя, кочнено, согласен что явных адресных констан нет.
PM MAIL WWW   Вверх
Ln78
Дата 27.4.2007, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



FiMa1, хорошо, что тебе понравилось, наверное в воскресенье-понедельник попробую дописать вторую часть. 
К продолжающим споритьЧестно говоря, я уже перестал понимать предмет спора. Может и 
остальные тоже спорят просто по инерции? Зайди сюда ортодоксальный астматик, он бы долго 
смеялся: "Я полагал, что между плюсанутыми и аштеэмельщиками разницы особой нет, но не 
настолько же? Придумали какое-то мифическое чудище, и сами же его и испугались". Вот, 
допустим, есть у нас структуры, описывающие разные физические сущности: корабль, 
автомобиль, кухонный стол, кролик, десяток кроликов. И есть ещё один тип: union, элементы 
которого - объекты перечисленных выше структур. Структуры содержат различные элементы, 
занимают разный объём памяти. Определена одна переменная, тип её - как раз тот самый
union. Я заполняю эту переменную данными, которые описывают автомобиль. Конечно, можно
считать фокусом: объявляю указатель на переменную как на автомобиль, потом чудом (просто 
указанием компилятору понимать его по-другому) рассматриваю это как кухонный стол, потом как кролика, а потом опять как автомобиль, и использую в последнем значении именно как автомобиль. И выдаю это за свои сверхспособности: смотрите какой фокусник. Да нет здесь никаких фокусов, и ловкости рук никакой нет, одно примитивное мошенничество. Что я могу, чтобы находящийся в здравом уме и трезвой памяти использовал в качестве кухонного стола автомобильное колесо с фарой и не заметил разницы? Или считается, что для int* и int** это чем-то принципиально отличается (подумаешь, втихаря нарисую/сотру звёздочку, никто и не заметит)?

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


Эксперт
****


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

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



Цитата(Daevaorn @  27.4.2007,  19:51 Найти цитируемый пост)
ну тут на самом деле вопрос интерпритации компилятором и процессором некого числа как адреса. хотя, кочнено, согласен что явных адресных констан нет.


Тут чье-то конкретное мнение уже точно не влияет, вот какие допустимые литеральные константы перечислены в стандарте:
Цитата

[lex.literal] 2.13 Literals
1 There are several kinds of literals.19)
literal:
integer-literal
character-literal
floating-literal
string-literal
boolean-literal


На большее стандартный компилятор не способен.  smile 

Цитата(Ln78 @  27.4.2007,  20:11 Найти цитируемый пост)
К продолжающим споритьЧестно говоря, я уже перестал понимать предмет спора.

Да тут уже спор совсем о  другом, чем изначально  smile Просто новую тему не стали начинать - так как все равно все об указателях да о передачи многомерок в функции.
Короче спорим помаленьку, пыхтим  smile 
PM MAIL ICQ   Вверх
JackYF
Дата 27.4.2007, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Две страницы я благополучно успел пропустить...
И все же спор у нас был о двух вещах:

1. тип "Массив" != тип "Указатель". Это так, теоретические изыскания.

2. Неправильная работа конкретного примера. То есть, что
Код

int a[3][4] { ... };

cout << a[2][3];

int **b = reinterpret_cast<int**>a;

cout << b[2][3];


Пример выведет два разных числа в лучшем случае. В худшем и AV/SegFault может схлопотать.


Ln78, а вообще во многом ты прав.
По данным двум пунктам мы спорили, спорили... А теперь о чем спорим?


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


Эксперт
****


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

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



Цитата(JackYF @  27.4.2007,  20:59 Найти цитируемый пост)
А теперь о чем спорим? 


Было  пожелание:

Цитата(Fazil6 @  27.4.2007,  10:09 Найти цитируемый пост)
с удовольствием ознакомлюсь с примером использования двумерного массива или его имени в качестве int**. Вполне сойдет ссылка на приводимые ранее примеры или свежачек какой-нить...


Я набросал пару примеров.

И началось...  smile 

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


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


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

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



Цитата(Anikmar @  27.4.2007,  21:06 Найти цитируемый пост)
И началось...  smile 

А ничего толком не началось. Корректного примера я так и не увидел. Или я что-то пропустил? Если да, то ткните в цитату или ссылку на этот корректный рабочий пример.

Начались опять какие-то разглагольствования. Итак, жду примера.


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


Эксперт
****


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

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



Цитата(JackYF @  28.4.2007,  13:50 Найти цитируемый пост)
Итак, жду примера. 

Ну уж нет. Привел два работающих кода. Если вам интересно - запустите их и откомпилируйте.
Если вы утверждаете, что работа с именем массива отличается от работы с двойным указателем - то аргументируйте и опровергайте.

А то получается какое-то барство. Сначала:
Цитата(JackYF @  27.4.2007,  20:59 Найти цитируемый пост)
Две страницы я благополучно успел пропустить...


А потом извольтес-с-с..:
Цитата(JackYF @  28.4.2007,  13:50 Найти цитируемый пост)
Начались опять какие-то разглагольствования. Итак, жду примера. 


У вас в роду дворян не былос-с-с?

 smile 
PM MAIL ICQ   Вверх
Fazil6
Дата 28.4.2007, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  27.4.2007,  18:29 Найти цитируемый пост)
Потому, что он таковым не является.

ну не является... 
Так почему ты считаешь что в строке 
Код

for (i=0;i<4;i++) printf("%d\t",*(*a)+i);

показано использование a как int**, если он таковым не является? 

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


Цитата(Anikmar @  27.4.2007,  18:29 Найти цитируемый пост)
Именно поэтому, работать с именем массива как с двойным указателем возможно, но он не является двойным указателем  сам по себе и передавать его в функцию, преобразовав к двойному указателю будет ошибкой.

Ох... Я просил пример, который доказывает, что массив или имя его можно использовать как int** ,  а не пример в котором показаны действия с неким массивом и "если бы переменная была int**, то выглядело бы все именно так". 


Цитата(Anikmar @  27.4.2007,  18:29 Найти цитируемый пост)
Нет и еще раз нет.

что нет?
Цитата(Anikmar @  27.4.2007,  18:29 Найти цитируемый пост)
char *s; - то это всегда указатель
char s[30]; - это совсем другой тип, это явно заданный массив и имеет тип char[30]

Я именно так и говорил всегда. 

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

такое впечатление, что ты единственный, кто знает о чем спорят...  Я, например, не уверен, что знаю... smile 


Цитата(JackYF @  28.4.2007,  13:50 Найти цитируемый пост)
А ничего толком не началось. Корректного примера я так и не увидел. Или я что-то пропустил?

ну принято считать что вот здесь пример демонстрирует
http://forum.vingrad.ru/index.php?showtopi...t&p=1114611
и вот тут
http://forum.vingrad.ru/index.php?showtopi...t&p=1114678

Добавлено через 9 минут и 47 секунд
Цитата(Anikmar @  28.4.2007,  23:25 Найти цитируемый пост)
Если вы утверждаете, что работа с именем массива отличается от работы с двойным указателем - то аргументируйте и опровергайте.

ну выглядит одинаково... На этом сходство заканчивается... Весь топик именно об этом, что даже когда работа с двумерным массивом может выглядеть как работа с указателем на указатель, ни массив ни его имя таковым не являются и не приводятся к такому типу и не представляются как такой тип(int**). 
PM MAIL   Вверх
Anikmar
Дата 28.4.2007, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  28.4.2007,  23:28 Найти цитируемый пост)
показано использование a как int**, если он таковым не является? 

Встречный вопрос. А как я с ним работаю с точки зрения конструкций языка? Привожу к другому типу? Я работаю с ним как с двойным указателем. Почему не так? С какими стандартными типами данных языка Си++ допустимы такие операции?

Цитата(Fazil6 @  28.4.2007,  23:28 Найти цитируемый пост)
У меня такое впечатление, что ты либо не читаешь что я пишу тебе вответ, либо не читал обсуждение до этого...

Обсуждения до этого хоть я и читал, к теме моего ответа никак не относятся. Я ни скем не спорил. Было предложение привести пример кода, в котром имя двухмерного массива использовылось бы как двойной указатель, причем правильно.
Я привел пример доступа к элементу массива, используя его имя в качестве двойного указателя. В чем я спорю, кого я оспорил и что я сделал неправильно? Имя массива использовалось как двойной указатель? ДА. Без каких либо ухищрений! Без приведений типа и т.п.
Доступ к элементу массива получили? ДА. 
Код рабочий? ДА!

А потом мне объяснют, что это частный случай, что int и указатель размером одинаковы и т.п. 

Я всего лишь ответил на пост. Дайте мне рабочий пример. - Дал. Работает - ДА. В чем я не прав, объясните?

Теперь получается, нет, он не подходит. Так как нельзя передать в функцию. Не вопрос. Передайте в функцию двойной массив не указывая его размерности? Используя только имя массива. Нельзя. Потому, что статический массив намертво привязан к своим измерениям. Таким образом, предложите мне пример функции, которая в качестве параметра получает статический двухмерный массив любой размерности. Давайте вместе разберем получившийся код.

Добавлено через 2 минуты и 24 секунды
P.S.
Цитата(Fazil6 @  28.4.2007,  23:28 Найти цитируемый пост)
ну выглядит одинаково... На этом сходство заканчивается... 

Язык си, конечно, допускает вольности. Но все-таки не с точки зрения того, что "выглядит одинаково" Правила семантического разбора предложения четко оговорены. И если я использовал конструкцию со звездачками без искусственного приведения типа, то компилятор для себя не делает варинтов "наверное это похоже на..." он действует четко (слова Богу). Так что эта фраза мне несколько непонятна.
PM MAIL ICQ   Вверх
Fazil6
Дата 29.4.2007, 00:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  28.4.2007,  23:44 Найти цитируемый пост)
А как я с ним работаю с точки зрения конструкций языка? Привожу к другому типу? Я работаю с ним как с двойным указателем. Почему не так? С какими стандартными типами данных языка Си++ допустимы такие операции?

Какие операции? Весь смысл примера сводится к тому, что **a даст в итоге значение типа int (если a это двумерный массив int). Я согласен с этим, но я говорю, что этот пример не доказвыает, что a это int**. Я просил пример, который это доказал бы. Поэтому я и говорю, что этот пример меня не устраивает. Поэтому я и вспоминаю передачу в функцию массива.

Цитата(Anikmar @  28.4.2007,  23:44 Найти цитируемый пост)
Язык си, конечно, допускает вольности. Но все-таки не с точки зрения того, что "выглядит одинаково" Правила семантического разбора предложения четко оговорены. И если я использовал конструкцию со звездачками без искусственного приведения типа, то компилятор для себя не делает варинтов "наверное это похоже на..." он действует четко (слова Богу). Так что эта фраза мне несколько непонятна.

ну да действует четко и я утверждаю, что когда компиллятор видит **a, действия его будут разными в зависимости от того какого типа a хоть мы и получаем в итоге int. И в твоем примере с конструкцией **а компиллятор работает как с указателем на массив , а не указателем на указатель на int

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


Эксперт
****


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

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



Цитата(Fazil6 @  29.4.2007,  00:11 Найти цитируемый пост)
 **a, действия его будут разными в зависимости от того какого типа a

??? действия его будут однозначны - получить значение <type>  - если a это int **a, то значение будет int. Какие зависимости?
Пример:
Код

    const int Xs = 3;
    const int Ys = 5;

    int a[Xs][Ys];
    int i,j;
    for (i=0;i<Xs;i++)
        for(j=0;j<Ys;j++) a[i][j] = 100 + i*10 + j;
    printf ("**a = %d\n",**a);

Будет выведен результат 100 и это однозначно. имя массива использовано как двойной указатель? ДА
Ваше требование:
Цитата(Fazil6 @  29.4.2007,  00:11 Найти цитируемый пост)
что **a даст в итоге значение типа int 

Выполнено? ДА!

Не понимаю... Какие примеры еще  надо привести?

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


Эксперт
***


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

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



Цитата(Anikmar @  29.4.2007,  00:21 Найти цитируемый пост)
действия его будут однозначны - получить значение <type>  - если a это int **a, то значение будет int. Какие зависимости?
 
зависимости от типа a. Компиллятор использует информацию о типе а для получения результата **а

Цитата(Anikmar @  29.4.2007,  00:21 Найти цитируемый пост)
имя массива использовано как двойной указатель? ДА

Нет. Имя массива использовано как указатель на массив, а не как двойной указатель и компиллятор действует в этом случае не так как если бы это был двойной указатель.  Я же писал, что **(a +1) в случае если a типа int** компиллятор выполнит смещение на sizeof(int*)*1, а если int a[2][2], то выполнит sizeof(int[2])*1 

sizeof в этих случаях выдает разные результаты и поэтому компилятор никогда не рассматривает двумерный массив как двойной указатель и **a выглядит как работа с двойным указателем , но на самом деле является работой с указателем на массив в твоем примере. Поэтому я и сказал, что меня этот пример не устраивает


Цитата(Anikmar @  29.4.2007,  00:21 Найти цитируемый пост)
Ваше требование:
 Это не мое требование. Это смысл твоего примера.
мое требование 
Цитата(Fazil6 @  29.4.2007,  00:11 Найти цитируемый пост)
Я согласен с этим, но я говорю, что этот пример не доказвыает, что a это int**. Я просил пример, который это доказал бы.

читай внимательнее, что я пишу
PM MAIL   Вверх
Anikmar
Дата 29.4.2007, 01:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  29.4.2007,  00:45 Найти цитируемый пост)
то выполнит sizeof(int[2])*1 

Что вы имели в виду?
PM MAIL ICQ   Вверх
Fazil6
Дата 29.4.2007, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  29.4.2007,  01:03 Найти цитируемый пост)
Что вы имели в виду?

смещение. Значение выражения a+1 при 
Код

int** a;

получим адрес на 4 больше, а при
Код

int a[2][2];

на 8 потому что sizeof(int[2]) == 8
PM MAIL   Вверх
Anikmar
Дата 29.4.2007, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



А что вы хотели? Мы не получим смещение 4 или 8. Мы получим следующий элемент массива. Для того, чтобы получить следующий элемент массива в случае объявления
int **p;
мы должны просто прибавить размер указателя
Так как у нас статический массив
int a[3][50];
то чтобы получить следующий элемент согласно правилам работы с двойными указателями компилятор высчитывает значение исходя из размерностей - так как статический массив занимает единый блок памяти. И прибавляет к нему 50 * sizeof(int).

Где нарущение правил работы с указателями???? Мы получили следующий элемент массива, согласно правилам языка Си.

В языке Си ( в стандарте) нет понятия многомерных массивов. Там есть понятие МАССИВ, доступ к элементам которго обозначается квадратными скобками. Если вы попытаетесь найти там операцию [][] - вы ее не найдете, потому, что ее там нет. Там есть понятие только массива. И понятие имени массива, которое приводится к указателя на тип данных массива.
Соответственно, если у нас есть объявление:
int a[3][12];
то с точки зрения станлдарта мы имеем массив из 3элеинтов, каждый из которых имеет тип int a[12]. Надеюсь с этим утверждением никто не спорит?

Далее читаем стандарт. Имя массива приводится к указателю на тип массива. (то же стандарт, а не мое мнение).
Значит наш пример показывает, что  мы имееем массив из 3элементов типа int[12], и что его имя приводится к указателюю на типа массива - т.е. на int[12]. При увеличении значения указателя на 1 мы должны получить следующий элемент массива. Так как у нас массив из 3элементов, каждый из которых имеет тип int[12] - то мы должны после инкрементирования укзателя получить следующий элемент массива, т.е. очереной int[12] пропуская все предыдущиие. Так как массив объявлен статически, то компилятор переставляет значение указателя так, чтобы он соответствовал правилам языка - т.е. на следующий элемент. Что мы и получаем в результате.

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

Иллюстрация к моим доводам на примере кода:
Код

    int b[2][3] = {{1,2,3},{4,5,6}};
    int i,j;
    
    for (i=0;i<2;i++)
        {
            for(j=0;j<3;j++) printf("%d\t",b[i][j]);
            printf("\n");
        }
    printf("**b = %d\n",**b);
    printf("**b = %d\n",**(b+1));


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

А если разницу, в поведении указателей вы усмотрели в различном смещении, то опять направляемся к стандарту:

При инкрементировании указателя, он увеличивается на значение, равное типу его хранения.
указатель
int **P
p хранит массив указателей, который размещен в памяти единым блоком. Последний по измерению массив по правилам языка Си всегда размещается единым блоком (стандарт)
При увеличении на единицу - он показывает следующий указатель - так как именно указатели он хранит. На какое конкретно число он увеличивается - стандартом не прописано (так как это программиста не касается). Нам гарантировано стандартом одно: при увеличении на 1 указатель устанавливается на следующий элемент (ну можно, конечно, и на 2 и на большее количество)
Операция sizeof в таких случаях никого никогда колыхать не должна - у нас есть указатель на конкретный тип данных и его инкрементирование указывает на следующий элемент.

При объявлении массива
p[3][nnnn]
Если мы инкрементируем значение p, то мы должны получить очередной элемент - т.е. указатель - т.к. p - приводится к массиву указателей по стандарту. На сколько пришлось реально инкрементировать (или декрементировать - уже стебусь  smile ) указатель программиста никак не касается. Прямая арияметика с указателями запрещена. нам гарантируется только следующий элемент. И мы его получаем - это следующий указатель.


В чем разница в поведении?

Это сообщение отредактировал(а) Anikmar - 29.4.2007, 03:39
PM MAIL ICQ   Вверх
Mayk
Дата 29.4.2007, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

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



Цитата(Anikmar @  29.4.2007,  05:32 Найти цитируемый пост)
int a[3][12];
то с точки зрения станлдарта мы имеем массив из 12 элеинтов, каждый из которых имеет тип int a[3]. Надеюсь с этим утверждением никто не спорит?

занудутствую: Наоборот. a - это массив из трёх элементов, каждый из которых является массивом из двенадцати элементов, каждый из которых является int'ом. 

зы. 6 последних страниц не читал. 2 и 3 тоже. 


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Anikmar
Дата 29.4.2007, 01:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Mayk @  29.4.2007,  01:43 Найти цитируемый пост)
Наоборот. a - это массив из трёх элементов, каждый из которых является массивом из двенадцати элементов, каждый из которых является int'ом

Эх.... Все-таки подсадили.  smile 

Как правильно пишется ЗоНУДА и ЗаНУДА?  smile 

Фраза из анекдота:
Цитата

Мужик, ну ты меня понял?


ПРОШУ СЧИТАТЬ ОЧЕПЯТКОЙ  smile

Добавлено @ 01:47
P.S.

И ваще - в 2 часа ночи что угодно перепутать можно, а не только порядок измерений.

Mayk - абсолютно прав, но смысл от этого никак не меняется

P.P.S.
Очепятка исправлена.

Это сообщение отредактировал(а) Anikmar - 29.4.2007, 03:41
PM MAIL ICQ   Вверх
Fazil6
Дата 29.4.2007, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
то чтобы получить следующий элемент согласно правилам работы с двойными указателями компилятор высчитывает значение исходя из размерностей - так как статический массив занимает единый блок памяти. И прибавляет к нему 50 * sizeof(int).

вообще-то sizeof(int[50]) потому что элементом, на который указывает указатель а является int[50]. И никаких правил работы с двойными или тройными или еще какими указателями нет. Есть арифметика указателей и важно в ней только на что указывает указатель. Для двойного указателя он указывает на int*, а для массива на int[50]. Вот их размер в байтах и важен

Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
А что вы хотели? Мы не получим смещение 4 или 8. Мы получим следующий элемент массива.
. Причем здесь массив? Указателю прибавляется 1 и в результате получаем некое значение адреса. а + 1
Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
Где нарущение правил работы с указателями???? Мы получили следующий элемент массива, согласно правилам языка Си.

ох.... Я разве сказал, что правила нарушены? Я разве говорил, что пример не работает? Я сразу сказал, что правила по которым этот пример работает разные в случаях двойного указателя и массива.
Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
Далее читаем стандарт. Имя массива приводится к указателю на тип массива. (то же стандарт, а не мое мнение).Значит наш пример показывает, что  мы имееем массив из 3элементов типа int[12], и что его имя приводится к указателюю на типа массива - т.е. на int[12].

как солнце из-за туч!!!! Только непонятно что ты читал в топике предыдущие 10 страниц....

Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
Если и эти доводы вас не убедили, тогда уже надо обращаться в артибтраж к Страуструпу - дескать какую-то хрень ты написал...

доводы чего? того что я тебе первым делом сказал? Теперь ты мне объясняешь как по стандарту... Именно потому что так по стандарту меня твои примеры и не устроили. Я тебе так сразу и сказал.


Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
При инкрементировании указателя, он увеличивается на значение, равное типу его хранения.указатель
int **P
p хранит массив указателей, который размещен в памяти единым блоком. Последний по измерению массив по правилам языка Си всегда размещается единым блоком (стандарт)
 хранит он указатель на указатель. Все. Никаких массивов здесь нет.

Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
Если мы инкрементируем значение p, то мы должны получить очередной элемент - т.е. указатель - т.к. p - приводится к массиву указателей по стандарту.
 по какому стандарту????? К какому массиву указателей????  единственное к чему он приводится - указатель на массив

Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
Если мы инкрементируем значение p, то мы должны получить очередной элемент - т.е. указатель


Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
В чем разница в поведении?


в том как компиллятор получает этот очередной элемент

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


Эксперт
****


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

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



Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
И никаких правил работы с двойными или тройными или еще какими указателями нет. Есть арифметика указателей

С этого момента по подробнее.
Итак имеем арифметику указателей.
Имеем 
char *s;  При операции s+1 указатель увеличивается так, чтобы указать на следующий элемент массива. По сути
Имеем 
char * *s; Теперь s указывает на указатель. s+1 прибавляет так же 1 адрес, чтобы указать на следующий элемент
Имеем
char s[3][30]; При операции s+1 он должен указать на следующий указатель. Именно для того, чтобы имя двухмерного массива соответствовало двойному указателю компилятор прибавляет к значению указателя сразу целую строку. Именно для того, чтобы арифметика указателей была одинаковой в поведении со статическими массивами и двойными указателями. А так как значение адреса статического массива по сути "только для чтения", то компилятор нне рискует тем, что если обратиться к имени массива как к указателю и попытаться что-нибудь ему присвоить, то естественно вылезет ошибка - так как указатели на подмассивы нигде не хранятся, а вычисляются по мере обращения. Это как раз и есть то отличие, почему имя двухмерного массива не является двойным указателем в чистом виде.

Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
Я разве сказал, что правила нарушены? Я разве говорил, что пример не работает? Я сразу сказал, что правила по которым этот пример работает разные в случаях двойного указателя и массива.

Никаких разных! Статический массив инициализирован! Поэтому прибавление к имени массива 1 позволяет сразу указать на след. элемент!
char a[3][30];
a - приводится к двойному указателю на 1-й элемент массива.
При прибавлении 1 а увеличивается на размер элемента хранения, в данном случае char[30] так как a имеет явный тип 3 указателя на массивы из 30 элементов
Вы же не будете спорить, что
void *p; - является указателем?
Будьте добры, приведите арифметику указателей примениму к типу void? 
Арифметика указателей обязательно будет работать по-разному в зависимости от типа указателя. Кто с этим спорит?
Я утверждаю, что двухмерные массивы С++ приводятся к двойному указателю согласно правилам стандарта.

Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
Теперь ты мне объясняешь как по стандарту... Именно потому что так по стандарту меня твои примеры и не устроили. Я тебе так сразу и сказал.

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

Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
ранит он указатель на указатель. Все. Никаких массивов здесь нет.

Откуда такая уверенность? Вы видели как выделилась память? Это указатель на двухмерный динамический массив. 
Посмотрите на объявление функции.
void PrintMas(int**P,int a, int b)
Скажите с такой же уверенностью: что храниться в переменной P?
Возьмем одномерный массив.
char *s;
Это указатель или массив? Пока мы непроинициализировали указатель - это неизвестно. В зависимости от того, что мы присвоим это может быть адрес переменной и адрес первого элемента массива.

Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
по какому стандарту????? К какому массиву указателей????  единственное к чему он приводится - указатель на массив

Т.е. вы говорите, что приведенное мной объявление
int **p; 
приводится к указателю на массив? У нас всего лишь двойной указатель - вы же сами говорили:
Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
хранит он указатель на указатель. Все. Никаких массивов здесь нет.


К какому массиву указателей? 
Он может содержать адрес конкретной переменной типа "Указатель на int" или адрес первого элемента массива таких указателей. По аналогии с одномерными массивами, согласно стандарта языка Си.
int p; - одиночное значение int
int *p; - указатель на int или на массив из таких int-ов
int **p - указатель на указатель на int или на массив таких указателей

Приведите пример, как вы объявляете динамический массив? Давайте посмотрим и обсудим ваш код.



Цитата(Fazil6 @  29.4.2007,  10:08 Найти цитируемый пост)
Цитата(Anikmar @  29.4.2007,  01:32 )
В чем разница в поведении?

в том как компиллятор получает этот очередной элемент

Разница поведения компилятора - это не разница поведения указателей. Именно для того, чтобы привести имя двухмерного массива к двойному указателю компилятор и ведет себя по-разному. Как же иначе? Зато указатели ведут себя адекватно.
PM MAIL ICQ   Вверх
Fazil6
Дата 29.4.2007, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
char s[3][30]; При операции s+1 он должен указать на следующий указатель. Именно для того, чтобы имя двухмерного массива соответствовало двойному указателю компилятор прибавляет к значению указателя сразу целую строку.

С чего ты взял, что компиллятор стремится чтобы 
Цитата

 имя двухмерного массива соответствовало двойному указателю 

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


Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
 Именно для того, чтобы арифметика указателей была одинаковой в поведении со статическими массивами и двойными указателями.

хм... она и так везде одинаковая... Повторяю, что компилятор четко разделяет статические массивы и  двойными указателями.

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Никаких разных! Статический массив инициализирован! Поэтому прибавление к имени массива 1 позволяет сразу указать на след. элемент!
 ТЫ читаешь что я пишу? То что мы получаем указатель на следующий элемент - это результат. Я говорю о том как получается этот результат. Ты же сам пишешь

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

Вот я и говорю, какого художника вы утверждаете что **(a + 1) работает с int**,  если a + 1 дает смещение не на размер int* , а на размер подмассива? Только не надо говорить , что смещение на размер подмассива для того чтобы  соответствовало двойному указателю.

 

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

нет. Нет такого правила в стандарте... Есть правило по поводу просто массива, но это правило не рекурсивно и переносить его на многомерные массивы нельзя.

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Я не увидел ни одного вашего встречного примера - как должно быть.

Дискуссия с тобой началась с моих примеров.... 

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

ну применил ты разыменовывание, ну получил ты в итоге int. По твоему это доказывет, что тип разыменовываемого int**? Я говорю, что тип того, что ты разымновывал int (*)[n] (указатель на массив из n элементов). Если его имя разыменовать 2 раза получим int. Вот  меня и не устраивает твой пример в котором двойным указателем и не пахнет.


Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Откуда такая уверенность? Вы видели как выделилась память? Это указатель на двухмерный динамический массив.

я вижу объявление и этого достаточно, чтобы однозначно определить тип. Нет такого типа указатель на двухмерный динамический массив и в арифметике указателей твое p будет использоваться как указатель на int* и никак подругому.  Вообще причем здесьэти экскурсы в динамическое выделение. Твой двухмерный динамический массив совершенно подругому расположен в памяти и то, что тут именно двойной указатель я не спорю

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
void PrintMas(int**P,int a, int b)
Скажите с такой же уверенностью: что храниться в переменной P?
 Ну точно ведь не int[2][2]. Уверен на 100%

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Возьмем одномерный массив.char *s;Это указатель или массив? Пока мы непроинициализировали указатель - это неизвестно. В зависимости от того, что мы присвоим это может быть адрес переменной и адрес первого элемента массива.

как его не инициализируй, но тип его не изменится. Это указатель на char. Даже new[] не сделает из него массива и его арифментика будет основываться на размере char. Мы говорим о нормальных класических статических массивах и динамические массивы идут в сад... 

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Приведите пример, как вы объявляете динамический массив? Давайте посмотрим и обсудим ваш код.

повторяю, динамические массивы нервно курят в саду... Речь не о них.

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Т.е. вы говорите, что приведенное мной объявлениеint **p; приводится к указателю на массив? У нас всего лишь двойной указатель - вы же сами говорили

ну не надо передергивать... 
было ведь так
Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
При объявлении массива
p[3][nnnn]
Если мы инкрементируем значение p, то мы должны получить очередной элемент - т.е. указатель - т.к. p - приводится к массиву указателей по стандарту.
 ни по какому стандарту он к массиву указателей не приводится.

Цитата(Anikmar @  29.4.2007,  11:08 Найти цитируемый пост)
Именно для того, чтобы привести имя двухмерного массива к двойному указателю компилятор и ведет себя по-разному.
 Компилятор ведет себя поразному потому что это разные типы, а не потому что ему нужно чтобы они привелись один другому
PM MAIL   Вверх
Xenon
Дата 29.4.2007, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Anikmar
Цитата(Anikmar @  29.4.2007,  01:32 Найти цитируемый пост)
p[3][nnnn]Если мы инкрементируем значение p

Код

p[3][nnnn];
++p;

Это что, работать должно? p - не l-value, к нему не может быть применем инкремент.


--------------------
user posted image  
PM MAIL   Вверх
Anikmar
Дата 29.4.2007, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Xenon @  29.4.2007,  16:15 Найти цитируемый пост)
Это что, работать должно? p - не l-value, к нему не может быть применем инкремент. 

В моем примере p был указан как **p

Инкремент я имел саму операцию увеличения указателя на 1 без его изменения в таком смысле:
int p[3][4];

*(p+1).... Так мы же можем делать и никто нас не убьет за это


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

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

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

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

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

Сейчас я уже начинаю себя ловить на мысли, что мне надо доказать вам, что имя двойного массива ЯВЛЯЕТСЯ двойным указателем. Нет. Двухмерный массвив не является двойным указателем. Его лишь можно так рассматривать по одной причине:

В языке Си имя одномерного массива можно рассматривать как указатель на его первый элемент. Т.е. как указатель на тип данных массива:
Утверждение 1
<type> Ar[NNN] - т.е. имя такого массива можно рассматривать как тип <type> *

Переходим к второму измерению
<type>Ar[MMM][NNN] Теперь Ar имеет тип Массив из MMM элементов, каждый из которых является массивоим из NNN элементов типа type.
Согласно утверждению  1, имя массива можно рассматривать как указатель на его первый элемент. Т.е. в нашем случае имя массива это указатель на 1-й массив (ну вернее нулевой) из NNN Элементов. Т.е. указатель на <type>[NNN]

<type>.[NNN] в первой части нашего утверждения ужы была рссмотрено как <type>*. Значит мы можем рассматривать имя двухмерного массива как указатель на <type>* что является <type>**

Если эти же рассуждения перевести к другой логике, то можно рассмотреть ее так:
typedef a10 int[10];

a10 a;             // Если взять отдельно a, то она может рассматривать как указатель на int и может вести себя именно так. 
                       //Имя одномерного   массива является указателем на его первый элемент, значит int*
a10 aa[10];    // Имя массива является указателем на 1-й элемент. Т.е. имеет тип *int[10]. 
                       // Последний в свою очередь может быть рассмотрен как int* Следовательно aa можно рассмотреть как int**

Еще раз повторю, фразы : "может быть рассмотрен", "с ним можно работать как" не синонимамы фраз "является"

Что собственно я вам показал и доказал примерами своего кода. А варианты, "А покажите мне код где с именем массива работают как с двойным указателем, и чтобы еще его значения соответсвовали двойному указателю" совершенно нелогичны.
Вообще, тип *int[40] не является стандартным  типом языка C. Это уже инициализированный тип. Поэтому всегда можно сказать, что операции с ними отличаются от опреаций int **.
Ну так int [][45] будут отличаться от int [][50]. Это что, тоже разные типы? Или все-таки частные случаи? Общия то базовый подоход операции [][] - это именно двойной указатель. И Именно к этому базовому подходу и подгоняет компилятор свои действия. 
Конкретно операция [][], применяемая к двойному указателю является аналогом разыменования. В случае со статтическим массив (но это является как раз именно частным случаем общего подхода) арифметика несколько упрощается, но не более. Опять таки пока мы не попробовали передать статический двухмерный массив произвольного размера в функцию. Там экономия на отсутствии реально хранящихся указателей вылиывается в проблему рассчета смещения. За все надо платить.
Но общий подход всегда базируется на каком-либо базовом типе, а базовый тип - это двойной указатель, так как нету в языке си типа [][].




PM MAIL ICQ   Вверх
nickless
Дата 29.4.2007, 17:25 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


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

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



 smile Народ, вам не надоело еще спорить, а? smile 

Немного статистики для сравнения:
"Win vs. Lin": 122 дня, 453 поста = 3,71 поста/день
"Собираем поклонников висты": 12 дней, 147 постов = 12,25 поста/день (это при активном участии тролля)
Эта тема: 9 дней, 172 поста = 19,11 поста/день  smile 

Вывод: религиозные войны отдыхают smile  smile 

Ладно, больше не буду вам мешать smile 


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
Fazil6
Дата 29.4.2007, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



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

такие, когда будет видно, что имя используется именно как тип int**. Я тебе уже говорил, что таких примеров мне неведомо ибо двумерный массив никак не связан с двойным указателем. И имя двумерного массива никогда не используется как переменная типа int**. 
например это
Код

int a[2][2];
int **pa = a;

доказывает, что a может использоваться как int**, и если бы такое выражение было корректно в С++ , то этого хватило бы для доказательства моей НЕПРАВОТЫ и безграмотности.
Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Я просил вас привести некоторые примеры - вы настойчиво заняли позицию нет это не то. Понимаете, у меня нет цели вам продать какой-либо продукт, а вы как придирчивый покупатель не хотите его покупать.

какие еще конкретные примеры??? С чего твои наезды на меня начались??? Посмотри внимательно.... 
http://forum.vingrad.ru/index.php?showtopi...t&p=1114163
там полно примеров.

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Изначально ваш вопрос звучал так: Покажите мне примеры, где с именем массива работают так же как с двойным указателем.

Неправда. Вот как он прозвучал.
Цитата(Fazil6 @  27.4.2007,  10:09 Найти цитируемый пост)
с удовольствием ознакомлюсь с примером использования двумерного массива или его имени в качестве int**



Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Я вам показал рабочие примеры, которые не просто показывали что это работает, но и несли смысловую нагрузку - доступ к строке матрицы и к конкретному элементу.

ты показал как двойной указатель использовать в качестве двумерного массива. Я не это спрашивал.

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Сейчас я уже начинаю себя ловить на мысли, что мне надо доказать вам, что имя двойного массива ЯВЛЯЕТСЯ двойным указателем.

ну вобщем смысл был таким. Если вы утверждаете что int[2][2] и int** както связаны (имя или еще что-то) то приведите примеры из которых это будет видно.

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
В языке Си имя одномерного массива можно рассматривать как указатель на его первый элемент. 
Т.е. как указатель на тип данных массива:
Утверждение 1<type> Ar[NNN] - т.е. имя такого массива можно рассматривать как тип <type> *
да. Только не рассматривать а использовать где это нужно.

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Переходим к второму измерению<type>Ar[MMM][NNN] Теперь Ar имеет тип Массив из MMM элементов, каждый из которых является массивоим из NNN элементов типа type.Согласно утверждению  1, имя массива можно рассматривать как указатель на его первый элемент. Т.е. в нашем случае имя массива это указатель на 1-й массив (ну вернее нулевой) из NNN Элементов. Т.е. указатель на <type>[NNN]

вот здесь стоило остановиться ибо на этом рассуждения заканчиваются и дальнейшие умозаключения неправильны

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
<type>.[NNN] в первой части нашего утверждения ужы была рссмотрено как <type>*. Значит мы можем рассматривать имя двухмерного массива как указатель на <type>* что является <type>**

ну вот это и неправильно. Это заблуждение. Я уже раз пять повторил!!!! Правило относящееся к одномерному массиву нерекурсивно!!!! Если мы можем рассматривать имя двумерного массива, то приведите мне пример где оно рассматривается компилятором как int**. Не надо хвататься за клаву. Нет таких примеров...
Ты говоришь, что в примере **a - это работа с двойным указателем потому что получили int. Я говорю, что это работа с указателем на int[n] , а двойным указателем здесь не пахнет. 


Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Ну так int [][45] будут отличаться от int [][50]. Это что, тоже разные типы? Или все-таки частные случаи?

конечно это разные типы.

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Общия то базовый подоход операции [][] - это именно двойной указатель. И Именно к этому базовому подходу и подгоняет компилятор свои действия. 

Бред.... Ничего компилятор никуда не подгоняет.

Цитата(Anikmar @  29.4.2007,  17:00 Найти цитируемый пост)
Но общий подход всегда базируется на каком-либо базовом типе, а базовый тип - это двойной указатель, так как нету в языке си типа [][]

ну договорились... Получается есть в языке си тип "двойной указатель"...

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


Эксперт
****


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

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



Цитата(Fazil6 @  29.4.2007,  18:04 Найти цитируемый пост)
Цитата(Anikmar @  29.4.2007,  17:00 )
<type>.[NNN] в первой части нашего утверждения ужы была рссмотрено как <type>*. Значит мы можем рассматривать имя двухмерного массива как указатель на <type>* что является <type>**

ну вот это и неправильно. Это заблуждение. Я уже раз пять повторил!!!! Правило относящееся к одномерному массиву нерекурсивно!!!! Если мы можем рассматривать имя двумерного массива, то приведите мне пример где оно рассматривается компилятором как int**. Не надо хвататься за клаву. Нет таких примеров...
Ты говоришь, что в примере **a - это работа с двойным указателем потому что получили int. Я говорю, что это работа с указателем на int[n] , а двойным указателем здесь не пахнет. 


Наконец то из нашего баяна только один пост более мнее выделить можно.

Откуда такая уверенность в этом: 
Правило относящееся к одномерному массиву нерекурсивно!!!! Это вы прочитали в стандарте?

Еще раз рассмотрим int[n]. Это массив целых чисел, который может быть приведен к указателю на int. Причем приведен имено по стандарту - без всяких приведений типа. По сути компилятор это делает неявно:
int a[45];
int *b=a;
Так что имя одномерного массива практически является указателм на тип - так как приводится неявно. И почему это правило должно быть нерекурсивно? И главное где это написано?

Цитата(Fazil6 @  29.4.2007,  18:04 Найти цитируемый пост)
Если мы можем рассматривать имя двумерного массива, то приведите мне пример где оно рассматривается компилятором как int**
 
Предлагаю остановиться на этом примере:
int a[3][4];
int b = **a;


PM MAIL ICQ   Вверх
MAKCim
Дата 29.4.2007, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



господа
посмотрите ассемблерный код и все станет понятно  smile 


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

PM MAIL   Вверх
Fazil6
Дата 29.4.2007, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Anikmar @  29.4.2007,  19:57 Найти цитируемый пост)
Предлагаю остановиться на этом примере:
int a[3][4];
int b = **a;

будем ходить по кругу? Нет здесь int**
Для наглядности 
Цитата

int b = **(a + 1);

если а используется как указатель на int* , то выражение (a + 1) должно дать адрес на sizeof(int*) больший чем a, но мы получаем адрес больший на sizeof(int[4]) поэтому делаем вывод, что a здесь используется как указатель на int[4] , который в свою очередь никак не приводится к int** ибо  тогда неправильно будет работать арифметика указателей и поэтому правило нерекурсивно


Это сообщение отредактировал(а) Fazil6 - 29.4.2007, 21:23
PM MAIL   Вверх
Dov
Дата 29.4.2007, 22:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(Fazil6 @  29.4.2007,  21:23 Найти цитируемый пост)
поэтому делаем вывод
Никакой такой вывод мы не делаем. А просто вспоминаем, что имя массива не обычный указатель, а особенный, имеющий несколько ограничений, по сравнению с обычным указателем. 
  Могу перечислить те, что знаю и помню. 
Код

int ar[4];
int* p;
int var;

ar = p; // нельзя так присваивать, потому что указатель ar - константный  
ar++;   // нельзя инкрементировать / декрементировать по той же причине
p = &ar;// нельзя, оператор '&' применим только к переменным, а не к именам массивов. Исключение 
        // составляет оператор вывода, например: cout << &ar << endl; но и в этом случае будет выведен
        // адрес первого элемента массива, а не адрес самого массива

И последнее. Оператор sizeof(ar), используя имя массива в качестве аргумента возвращает размер всего массива в байтах, а не размер указателя. То есть в данном примере вернёт 16, а не 4.




--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Anikmar
Дата 29.4.2007, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Fazil6 @  29.4.2007,  21:23 Найти цитируемый пост)
будем ходить по кругу? Нет здесь int**

Если вам будет легче, то int** является базовым типом для массива. Массив это частный случай поведения, в том числе и рассчета указателя. Еще раз повторю, в связи с тем что массив не является int**, но должен вести себя как int  арифметика в нем естественно работает по-другому.
Если говорить о нерекурсивности (я вообще не особо понимаю при чем здесь этот термин, но в общем то понятно)
то:
int a[5];
int *aa = a;
Преобразование стандартное, все в порядке, но sizeof(a) и sizeof(aa) также будут отличаться. Однако это ведь вас не смущает? Тем не менее a ведет себя как указатель на int, тогда согласно вашей логике это не так - так как sizeof дают разные результаты? 
Еще раз повторяю:
Я не говорю, что имя двухмерного массива является двойным указателем. Можно сказать, что это производный тип двойного указателя с перегруженной арифметикой. Однако если работать с ним как с двойным указателем он выдает именно тот результат, который ожидается.

Этому посвящена отдельная глава стандарта (8.3) Там описана схема преобразования имени массива в указатель
PM MAIL ICQ   Вверх
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 и все желающие – получите обещанное окончание. Там есть обращение и к apookLikehoodthreef – основное содержание вам вряд ли будет интересно, но последние 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 
Fazil6apookAnikmarJackYF
что это вы на 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   Вверх
FiMa1
Дата 3.5.2007, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Очередной вопрос..
Цитата
Код
int main()
{
    int arr[10] = { 0, 1, 2 };
    int *pArr[5];

    pArr[0] = arr;

    pArr[0][1] = 4;

Строку инициализации указателя pArr[0] компилятор приводит к виду *(*(pArr + 0) + 1) = 4; ?
Нагло воспользовавшись твоими знаниями попытаюсь удовлетворить свою любознательность..
Цитата
Для трёх других вариантов – мы обязаны были это сделать, иначе компилятор сильно бы удивился: как же ты собираешься использовать эти константы, когда ты не дал им значений, ведь другого шанса определить их у тебя не будет?

Почему компилятор MS VS.NET 2003 разрешает создать такую структуру, ведь обратиться к ее члену будет невозможно, т.к. имя создаваемому структурой типу не дано?
Код
struct {
    int a;
};

Если верить codelord, то не рулит компилятор MS.. ?

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 777
Регистрация: 7.5.2005
Где: ты моя темноглаза я где?!

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



gcc 
Цитата

 ошибка: абстрактный декларатор ‘<anonymous struct>’ использован в качестве декларатора


Это сообщение отредактировал(а) codelord - 3.5.2007, 16:30


--------------------
Доступен поиск по исходным кодам в GOOGLE.
http://www.google.com/codesearch
PM MAIL   Вверх
Ln78
Дата 3.5.2007, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



На первый вопрос - да.
На второй (несколько выходит за тему топика) строгого формального ответа не знаю, но как бы я это объяснил для себя: это объявление сродни описанию неиспользованной переменной: пользы от неё никакой, но и вреда тоже. В случае с константами ситуация другая: если компилятор обработал такое определение переменной, то предполагается, что к ней можно обращаться за значением, а поскольку у неё значения нет - воспринимается как ошибка. 
Формально правильнее, наверное, можно было бы сказать: синтаксис такой, то нельзя, а это можно. Но, учитывая, что синтаксис создавался предварительно подумав, логика какая-то быть должна. А поскольку не я определял синтаксис, точного объяснения дать не могу. Можешь создать ещё один топик по этой теме, возможно, получишь много интересных вариантов в ответ.
PM MAIL   Вверх
FiMa1
Дата 4.5.2007, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Имя одномерного массива - это константа, представляющая собой указатель на 0-ой элемент массива. Этот указатель отличается от обычных тем, что его нельзя изменить (установить на другую переменную), поскольку он сам хранится не в переменной, а  является  просто некоторым постоянным адресом. Андрей Богатырев. Хрестоматия по программированию на Си в Unix
Как таки будет выглядеть определение для МНОГОМЕРНОГО массива?
PM   Вверх
Dov
Дата 4.5.2007, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

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



Цитата(FiMa1 @  4.5.2007,  10:32 Найти цитируемый пост)
Как таки будет выглядеть определение для МНОГОМЕРНОГО массива?

FiMa1, а сам-то ты как думаешь?

Намёк: многомерный массив представляет собой одномерный массив массивов.  smile 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Страницы: (14) [Все] 1 2 3 ... Последняя »
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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