|
|
||||||||||||||||
[Задача] Адресная арифметика08.03.2012, 12:38. Показов 9141. Ответов 49
Метки задачи от evg (Все метки)
Просьба к модераторам: НЕ надо перетаскивать в разделы типа "Си\Си++ для экспертов"
Пример возник на основе реальной программы. Пример содержит ошибку, а потому не факт, что повторится на всех компиляторах. В моём случае ошибка проявлялась на i386-linux32 при использовании компилятора gcc.
Добавлено через 29 минут Традиционная просьба прятать догадки и ответы под CUT'ом
0
|
||||||||||||||||
| 08.03.2012, 12:38 | |
|
Ответы с готовыми решениями:
49
адресная арифметика Адресная арифметика Адресная арифметика |
|
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
|
||||||||
| 08.03.2012, 13:56 | ||||||||
|
Другой(верный) результат
Добавлено через 6 минут
0
|
||||||||
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
||||||
| 08.03.2012, 14:02 | ||||||
|
у меня компилятор в адресном пространстве переставил местами a и b, но это не суть важно
судя по результату дизассемблирования компилятор у меня b находится в $0x804a014 a - в $0x804a015 переменной tmp вообще нету, вместо нее компилятор подставляет адрес $0x804a014
баг компилятор на лицо
0
|
||||||
|
|
|||
| 08.03.2012, 14:13 [ТС] | |||
|
Там, где компилятор поменял местами "a" и "b" нужно изменить выражение "&a + 1" на "&a - 1". Я специально вставил печать разницы адресов. Чтобы если что-то не так, то подправить то место, где через адрес одной переменной мы получаем адрес другой переменной
Добавлено через 34 секунды
0
|
|||
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
||
| 08.03.2012, 14:14 | ||
|
собсно правильно начинает работать только при volatile-модификаторе у a и b - может в этом подвох?
0
|
||
|
|
||
| 08.03.2012, 14:16 [ТС] | ||
|
0
|
||
|
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
|
|||
| 08.03.2012, 14:22 | |||
|
alex_x_x, http://ideone.com/GaThh а вот такой результат?
Добавлено через 5 минут
0
|
|||
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
||
| 08.03.2012, 14:37 | ||
|
в данном случае обращение к b неявное, и судя по дизасму программы компилятор не учитывает, что b может измениться, и собсно поэтому хранит ее значение в регистре, хотя в памяти она меняется Добавлено через 13 секунд go, да
0
|
||
|
|
||||||
| 08.03.2012, 14:58 [ТС] | ||||||
|
alex_x_x, в следующем примере обращение к "b" тоже неявное, но ведь подобного косяка нет
0
|
||||||
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
|
| 08.03.2012, 15:12 | |
|
Evg, не согласен, тут все вполне явно и b не модифицируется через неявную арифметику указателей
ну вообщем, в любом случае в хорошем коде как в примере делать нельзя )
0
|
|
|
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
|
|
| 08.03.2012, 15:53 | |
|
тут по сути попытка модификации констант не?
Добавлено через 1 минуту при оптимизации компилятор подставляет именно значения констант
0
|
|
|
|
|||||||||||||||
| 08.03.2012, 16:15 [ТС] | |||||||||||||||
0
|
|||||||||||||||
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
|||
| 08.03.2012, 16:23 | |||
|
в оригинальном случае указатель получается путем арифметики с адресами а вот первоначальный - нет Добавлено через 2 минуты Evg, те по сути если мы в коде сделаем int* ptr = rand(); *ptr = 11; то компилятор практически не сможет в коде вокруг этой конструкции ничего оптимизировать (относительно хранения переменных в регистрах)
0
|
|||
|
|
||||||||||||||
| 08.03.2012, 16:30 [ТС] | ||||||||||||||
Добавлено через 1 минуту
0
|
||||||||||||||
|
Псевдослучайный
1946 / 1146 / 98
Регистрация: 13.09.2011
Сообщений: 3,215
|
|
| 08.03.2012, 16:40 | |
|
В любом случае нельзя делать никаких предположений насчёт взаимного расположения элементов из не непрерывных областей памяти, так что не очень понятно о чём спор...
0
|
|
|
|
|||||||
| 08.03.2012, 16:56 [ТС] | |||||||
Сообщение было отмечено как решение
РешениеКак оно на самом деле
По стандарту языка Си адресная арифметика "адрес + целое" определена только в тех случаях, когда и "адрес" и результат операции являются адресами внутри одного и того же объекта (переменной языка). В нашем случае значение "&a + 1" вываливается за границу переменной "a", а потому результат такой операции неопределён.
Данным свойством стандарта руководствуется компилятор при оптимизациях на современных процессорах, которые имеют возможность параллельного исполнения инструкций. Современные Intel'овские процессоры являются суперскалярами, которые состоят из нескольких исполняющих устройств, позволяющих исполнять операции в параллель. Для подобных процессоров компилятор пытается переупорядочить порядок исполнения операций, чтобы более долгие по времени исполнения операции исполнились как можно раньше (а в пвраллель будут исполняться более быстрые операции). Разумеется, такие перестановки допутимы только в тех случаях, когда компилятор может доказать, что перестановка операций не приведёт к тому, что изменится результат программы. Операция load (чтение из памяти) в современных процессорах является самой медленной операцией, потому как в случае отсутсвия данных в кэше операция исполняется чуть ли не 100 тактов. Это обусловлено сильно различающейся тактовой частоты процессора и памяти (а так же накладные расходы на работу контроллера памяти). Поэтому компилятор старается load'ы вытащить вперёд по исполнению. При этом требуется проверка на то, а не конфликтуют ли load'ы со store'ами (операциями записи в память). Т.е. если емеется операция записи в память, которая пишет в ту же ячейку памяти или возможно пишет в ту же ячейку памяти, то переставлять её с операцией load нельзя. В нашем случае компилятор видит операцию записи в память по адресу "&a + 1" и операцию чтения из памяти по адресу "&b". Пользуясь указанным выше свойтсвом стандарта компилятор, немного его перефразируя, трактует как "операции чтения и записи в разные объекты никогда не конфликтуют между собой и их всегда можно переставлять". Другими словами, если операции чтения и записи зацеплены за разные объекты, то при любой адресной арифметике можно считать, что их можно переставлять. Но это не так, если мы имеем дело, к примеру, с массивом. В этом случае чтение элемента a[i] можно переставлять с записью элемента a[j] только в том случае, если компилятор сможет доказать, что во всех случаях i != j. Поэтому в нашем примере компилятор переставил местами операторы "*(&a + 1) = 11;" и "tmp = b;", поскольку с точки зрения стандарта он имеет на это право. Ну и если кто-то посмотрит построенный код, то в явном виде это дело увидит. А вот когда есть просто указатель, взявшийся из какой-нибудь внешней функции, то компилятор НЕ имеет права переставлять store по этому указателю с любым load'ом, потому как он не сможет доказать, что эти обращения в память не конфликтуют между собой История данного примера была следующая. Давным-давно имелась программа, написанная на ассемблере. В программе были два массива "a" и "b" одинакового размера. Была некая функция, которая выполняла симметричную обработку этих массивов. Поскольку на ассемблере программист сам располагает объекты в памяти, то он сам гарантирует и разницу адресов между объектами. Поэтому для обработки массивов был написан код, в который на регистре передаётся адрес массива "a" через который можно достучаться до объекта "b". Таким образом, не нужно было дополнительного регистра для хранения адреса "b" (т.е. сэкономили на регистрах). Смысл кода был примерно такой (для простоты я его напишу на Си, хотя он был написан на ассемблере):
8
|
|||||||
|
Псевдослучайный
1946 / 1146 / 98
Регистрация: 13.09.2011
Сообщений: 3,215
|
||
| 08.03.2012, 17:03 | ||
|
0
|
||
|
|
||
| 08.03.2012, 17:07 [ТС] | ||
|
0
|
||
|
Псевдослучайный
1946 / 1146 / 98
Регистрация: 13.09.2011
Сообщений: 3,215
|
|
| 08.03.2012, 17:12 | |
|
Evg, delta может меняться в процессе исполнения.
0
|
|
|
|
||
| 08.03.2012, 17:22 [ТС] | ||
![]() Из квантовой теории следует, что если я с разбегу долбанусь в стену, то существует ненулевая вероятность того, что я пройду сквозь стену из-за туннельного эффекта. Если я напишу код "int x = 1000;" то есть шанс, что он отработает неправильно из-за того, что на каком-то компиляторе размер int'а равен 1, или на процессоре байт состоит из 2 битов, а не из 8, или ещё что-то. Могу привести ещё кучу примеров, которые в данном случае будут неуместны (как и твоё возражение)
0
|
||
| 08.03.2012, 17:22 | |
|
Помогаю со студенческими работами здесь
20
Адресная арифметика и массивы Указатели и адресная арифметика Указатели, адресная арифметика Адресная арифметика: поиск max элемента массива Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
|
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11
— это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
|
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11
Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
|
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
|
|
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/
O1rJuneU_ls
https:/ / vkvideo. ru/ video-115721503_456239114
|
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ВВЕДЕНИЕ
Введу сокращения:
аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
|
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi
ветка по-частям.
коммит Create переделка под биомассу. txt
вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
|
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ *
Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во
всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
|