|
Модераторы: Daevaorn |
|
AlanG |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 71 Регистрация: 11.5.2006 Где: РашЫн ФидирейшЫн Репутация: нет Всего: нет |
Всем доброго времени суток.
Возникли непонятки с указателями. К примеру есть указатель ссылающийся на определенный адрес, если его инкрементиролвать или декрементировать, то адрес изменяется на 2 значения, но только если тип данных занимает 2 байта. Вопрос: в чем суть таких действий, какая связь между длиной в байтах и адресом ячейки?
|
|||
|
||||
Daevaorn |
|
|||
Эксперт Профиль Группа: Комодератор Сообщений: 2155 Регистрация: 29.11.2004 Где: Москва Репутация: 51 Всего: 70 |
AlanG,
В твоём случае значит sizeof(int)==2, а поскольку p у тебя указатель именно на int, то и ++p и --p будет добавлять и убавлять от адреса 2. Вот если указатель был бы void*, то его нельзя ++/--, т.к. не определен тип. Арифметика указателей очень удобна при реализации сложных алгоритмов работы с памятью. |
|||
|
||||
AlanG |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 71 Регистрация: 11.5.2006 Где: РашЫн ФидирейшЫн Репутация: нет Всего: нет |
Да это я знаю , мне бы все о связь между длиной в байтах и адресом ячейки? |
|||
|
||||
likehood |
|
|||
666 Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
удобно работать с массивами: ++p переходит к следующему элементу массива.
|
|||
|
||||
LuckLess |
|
|||
Бывалый Профиль Группа: Участник Сообщений: 180 Регистрация: 15.9.2004 Репутация: 1 Всего: 1 |
++ и -- заставляют указатель указывать на следующий(++) или предыдущий(--) элемент ТАКОГО же типа, что и элемент на который он указывает.
логично предположить, что раз элемент занимает 2 байта, то следующий элемент будет через 2 байта после этого |
|||
|
||||
MAKCim |
|
|||
Воін дZэна Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
если
то ++p эквивалентно p+=sizeof(int); --p ... p-=sizeof(int) p+i ... p+i*sizeof(int) p-i ... p-i*sizeof(int) ... -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
bsa |
|
||||||
Эксперт Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
++p эквивалентно p += 1!!! Не надо путать!
|
||||||
|
|||||||
MAKCim |
|
|||
Воін дZэна Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 52 Всего: 207 |
ну да - sizeof неявно добавляется спасибо что заметил -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
AlanG |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 71 Регистрация: 11.5.2006 Где: РашЫн ФидирейшЫн Репутация: нет Всего: нет |
Народ , давайте разберем строение байта и разряды. Как вообще устроены разряды и байты?
Я, если чесно совсем не разбираюсь в строении ячеек памяти. Я знаю что такое байт, но я не знаю как он храница в ячейках. На данный момент в голове складывается следующая картина: Одна ячейка хранит в себе 1 байт. Если да, то инкремент адреса увеличивая на еденицу, прибавляет 2 байта, если тип данных имеет размер 2 байта. Получается что, инкрементируя адрес который несет в себе 1 байт, невольно перемещается на 2 байта, т.е. на две яцейка памяти? |
|||
|
||||
UnrealMan |
|
|||
Опытный Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Адресация памяти побайтовая. Запись
p = p+1 для указателя будет делать примерно то же, что и следующая: p = (T *)((char *)p+sizeof(T)); если p имеет тип T * Если тип int занимает 4 байта, то это значит, что под каждую переменную типа int будет отводиться чётверка байт. Записав p++; мы увеличиваем p таким образом, что он указывает теперь на начало следующей четвёрки байт, составляющей единое целое значение типа int. |
|||
|
||||
likehood |
|
|||
666 Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
надо определится, что называть ячейкой памяти. Чтобы не путать байты с ячейками будем считать, что ячейка - это область памяти, где храниться конкретная переменная. Для типа long ячейка состоит из четырех байт, идущих в памяти друг за другом. При этом адресом переменной (ячейки) называют адрес самого младшего ее байта (т.е. имеющего наименьший адрес). Выглядит это так:
если long *p указывает на 1-ю ячейку, то ++p увеличится на 4 байта и будет указывать на следующую ячейку. Такое поведение указателей сильно упрощает обработку массивов данных, но если нужно сдвинуть указатель только на один байт, надо сделать приведение к типу (byte*). |
|||
|
||||
AlanG |
|
||||
Шустрый Профиль Группа: Участник Сообщений: 71 Регистрация: 11.5.2006 Где: РашЫн ФидирейшЫн Репутация: нет Всего: нет |
Тогда лоника мне совсем не понятна. Ведь если переменная храница в одной ячейке, и если к примеру ячейка хранит в себе тип int размером в 2 байта, то зачем перескакивать через одну ячейку? Ведь мы инкрементируем адрес (ячейку).
P.S. Про байты и размеры байтов мне все понятно, пока не могу вкурить логику и само строение ячеек. Это сообщение отредактировал(а) AlanG - 16.5.2006, 11:41 |
||||
|
|||||
threef |
|
|||
Опытный Профиль Группа: Участник Сообщений: 375 Регистрация: 27.10.2005 Где: Запорожье Репутация: 9 Всего: 10 |
Тогда так
адрес байт(биты) переменные массив 0x00000000 76543210 long z; int x[4], x[0] 0x00000001 76543210 0x00000002 76543210 x[1] 0x00000003 76543210 0x00000004 76543210 long y; x[2] 0x00000005 76543210 0x00000006 76543210 x[3] 0x00000007 76543210 если у тебя переменная типа long находится по адресу 0x00000000 и занимает 4 байта, то адрес следующей - 0x00000004. &z+1 == &y Если размер int 2 байта и у тебя массив int , то каждый следующий элемент находится через 2 байта &x[0]+1==&x[1] &x[0]+2==&x[2] и т.д. В С /C++ адресная арифметика выполняется для типизированных указателей, бывает только целочисленной и прибавление целого числа к указателю дает новый адрес, смещенный на число * размер типа |
|||
|
||||
bsa |
|
||||||
Эксперт Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
baronp, про тип long ты не совсем прав. У меня он занимает в памяти 8 байт (у меня и машина 64-х битная, и ОС). А вот int у всех машин с разрядностью не менее 32-х бит - 4 байта.
AlanG Ты сам подумай, что легче написать: a += sizeof(*a) или a += 1? Естественно второй вариант. Случаи, когда нужно методом изменения указателя получить доступ к каждой ячейке очень редки и для этого используются всякие ухищрения, например p = (char*)a + 1, здесь p - это char*. Кстати, разница типизированных указателей равна расстоянию в элементах, а не байтах:
Результат будет 10. Это очень хорошая особенность C/C++. Без нее, было бы намного сложнее писать программы, оперирующие массивами структур. Да и они были бы менее читабельными. Но, повторяю, это особенность C/C++. Машинный код, который генерируется компилятором, прибавляет уже нужное количество байт:
Будет транслированно во что-то типа:
Здесь [bp+08h] - это адрес переменной a в стеке приложения, а 028h - это 40 в десятичной системе счисления. Если ассемблер для тебя не очень понятен, то объясню проще - работу по умножению 10 на размер элемента (т.е. 4) возьмет на себя компилятор. И процессор уже выполнить увеличение на 40, а не на 10. Но с точки зрения человека, запись 10 легче воспринимается, чем 40 - не надо делить, чтобы узнать, на какой элемент массива будет указывать указатель после выполнения данной операции. |
||||||
|
|||||||
AlanG |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 71 Регистрация: 11.5.2006 Где: РашЫн ФидирейшЫн Репутация: нет Всего: нет |
Ребят, здорого расписали, спасибо
(Жаль немогу репутацию повысить, но попрошу модераторов ) И еще мне кажется что пора книгу менять по C++. Что посоветуйте? |
|||
|
||||
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |