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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многомерные массивы и указатели, Как получить адрес элемента массива 
V
    Опции темы
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   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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