![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| FiMa1 |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
Очередной вопрос..
Строку инициализации указателя pArr[0] компилятор приводит к виду *(*(pArr + 0) + 1) = 4; ? Нагло воспользовавшись твоими знаниями попытаюсь удовлетворить свою любознательность..
Почему компилятор MS VS.NET 2003 разрешает создать такую структуру, ведь обратиться к ее члену будет невозможно, т.к. имя создаваемому структурой типу не дано?
Если верить codelord, то не рулит компилятор MS.. ? Это сообщение отредактировал(а) FiMa1 - 3.5.2007, 16:38 |
||||||||
|
|||||||||
| codelord |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 777 Регистрация: 7.5.2005 Где: ты моя темноглаза я где?! Репутация: 1 Всего: 39 |
gcc
Это сообщение отредактировал(а) codelord - 3.5.2007, 16:30 |
|||
|
||||
| Ln78 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 274 Регистрация: 25.11.2006 Репутация: 13 Всего: 15 |
На первый вопрос - да.
На второй (несколько выходит за тему топика) строгого формального ответа не знаю, но как бы я это объяснил для себя: это объявление сродни описанию неиспользованной переменной: пользы от неё никакой, но и вреда тоже. В случае с константами ситуация другая: если компилятор обработал такое определение переменной, то предполагается, что к ней можно обращаться за значением, а поскольку у неё значения нет - воспринимается как ошибка. Формально правильнее, наверное, можно было бы сказать: синтаксис такой, то нельзя, а это можно. Но, учитывая, что синтаксис создавался предварительно подумав, логика какая-то быть должна. А поскольку не я определял синтаксис, точного объяснения дать не могу. Можешь создать ещё один топик по этой теме, возможно, получишь много интересных вариантов в ответ. |
|||
|
||||
| FiMa1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
Имя одномерного массива - это константа, представляющая собой указатель на 0-ой элемент массива. Этот указатель отличается от обычных тем, что его нельзя изменить (установить на другую переменную), поскольку он сам хранится не в переменной, а является просто некоторым постоянным адресом. Андрей Богатырев. Хрестоматия по программированию на Си в Unix
Как таки будет выглядеть определение для МНОГОМЕРНОГО массива? |
|||
|
||||
| Dov |
|
|||
![]() аСинизатор ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1721 Регистрация: 10.5.2003 Где: Эрец-Исраэль Репутация: 15 Всего: 88 |
FiMa1, а сам-то ты как думаешь? Намёк: многомерный массив представляет собой одномерный массив массивов. -------------------- Тут вечности запах томительный, И свежие фрукты дешевые, А климат у нас – изумительный, И только соседи – #уевые. Игорь Губерман. |
|||
|
||||
| FiMa1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
Имя многомерного массива - это константный указатель на 0-ой элемент данного многомерного массива (здесь одномерный массив - константный указатель на 0-ой элемент данного одномерного массива). Это сообщение отредактировал(а) FiMa1 - 4.5.2007, 11:18 |
|||
|
||||
| Fazil6 |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
какой 0 в последней строке? Вся предыдущая дискуссия была о том, что представлять
неправильно. Правильно сказать Имя многомерного массива - это константный указатель на 0-ой элемент данного многомерного массива (здесь одномерный массив) поэтому и не будет работать
|
||||
|
|||||
| FiMa1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
Ок, если ma – обычный указатель, то зачем нужно явное его приведение к int*: int *p = (int *)ma; ?
В общем-то всё понятно. Не очевидным кажется только то, что имя массива ma - по определению указатель, но мы не можем использовать его как указатель без предварительного приведения к *int. Вот это прокомментируйте. пожалуйста. Это сообщение отредактировал(а) FiMa1 - 4.5.2007, 14:11 |
|||
|
||||
| Fazil6 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
ma - это не указатель по определению. Это имя массива можно использовать как указатель. В Твоем примере ma можно использовать как указатель на массив int[5] и поэтому
компилироваться не будет, но с приведением к int* работать будет потому, что адрес, с которым асоциировано имя ma - это, кроме всего прочего, и адрес первого элемента первого массива в твоем многомерном массиве, и через этот адрес посредством указателя int *p можно получить дотуп. |
|||
|
||||
| FiMa1 |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
Почему когда мы пишем
|
||||
|
|||||
| Fazil6 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1653 Регистрация: 3.5.2006 Где: Минск Репутация: 35 Всего: 60 |
он не инициализируется нулем. Он инициализируется адресом, асоциированным с ma, а по этому адресу лежит значение ma[0][0] , а так как ma[0][0] равно нулю и поэтому *p2 равно 0 , и поэтому **p2 - это попытка разыменовать нулевой адрес. Это сообщение отредактировал(а) Fazil6 - 4.5.2007, 15:54 |
|||
|
||||
| FiMa1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
С этим разобрался, спасибо! Далее Ln78 пишет (комменты мои):
Это сообщение отредактировал(а) FiMa1 - 4.5.2007, 16:14 |
|||
|
||||
| Ln78 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 274 Регистрация: 25.11.2006 Репутация: 13 Всего: 15 |
FiMa1, я рисовал таблички, чтобы пояснить, что там делается, посмотри на них внимательнее. Здесь мы указываем транслятору, чтобы он мог ту область памяти (3*5*4 байт) адресовать другим способом, как будто там расположен трёхмерный массив.
|
|||
|
||||
| FiMa1 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 408 Регистрация: 23.9.2006 Репутация: 5 Всего: 6 |
Надеюсь, что во всем разобрался... Сделал для себя ряд очевидных, для взгляда со стороны, выводов.
После объявления int arr[SIZE], получить доступ к элементам массива arr можно посредством имени переменной arr[0] и имени переменной-указателя arr. Такое многообразие дополнительных имен переменных дает просто больше возможностей для "общения" с компилятором. С другой стороны, важно знать, что ни для хранения самого имени arr[0], ни для имени arr никакой памяти не выделяется!!! С точки зрения компилятора, имя переменной - это синоним имени определенной ячейки памяти, ее символический адрес. Эта ячейка памяти может хранить данные — значение переменной. В то время, как сам объявленный массив arr имеет тип ТИП[SIZE], имя массива может быть использовано в качестве переменной типа КОНСТАНТНЫЙ_УКАЗАТЕЛЬ, который, по умолчанию проинициализирован нулевым элементом данного массива. Рассмотрим определение двумерного массива - int ma[3][3]; После данного определения вводится три имени переменных - ma, ma[0], ma[0][0]. Соответственно типов int[3][3], int[3] и int. Теперь имя массива ma может быть использовано в качестве указателя на его нулевой элемент, вместе с этим на разработчика ложится отвественность четко понимать, что, в данном случае, нулевым элементом массива ma является также массив, только одномерный – int ma[3], имя которого также может быть использовано в качестве указателя... Поэтому для доступа к нулевому элементу двумерного массива через указатель необходимо предварительное приведение к типу указатель: int *pa = (int *)ma; В общем, ОГРОМНОЕ всем спасибо за участие! Отдельная благодарность Ln78 за потраченное время и усилия на составление документов! Это сообщение отредактировал(а) FiMa1 - 10.5.2007, 10:59 |
|||
|
||||
| unicuum |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 830 Регистрация: 16.3.2005 Где: Рашка Репутация: 1 Всего: 8 |
Простой код без каких-либо фишек и хитростей языка:
Распечатка:
Таким образом с многомерными массивами можно работать и посредством указателя, указывающего на первый элемент массива. Иными словами для нашего случая это int*, а не int**. int** является указателем на указатель, следующая картинка схематически изображает память и нарисована мною чтобы разъяснить данный момент. ![]() 1. указатель на указатель содержит адрес указателя на целочисленное значение 2. указатель содержит адрес целочисленного значения 3. внутри самого первого элемента массива содержится конкретное значение, а не адрес Это сообщение отредактировал(а) unicuum - 20.4.2008, 05:57 -------------------- ![]() обычный день на винграде |
||||
|
|||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |