2009-11-24 6 views
6

Извините, если это просто, мой C++ ржавый.слегка странный код на C++

Что это такое? Насколько я могу видеть, нет назначения или вызова функции. Этот код повторяется много раз в некотором коде, который я унаследовал. Если это имеет значение, это встроенный код.

*(volatile UINT16 *)&someVar->something; 

редактирование: продолжение оттуда, подтверждает ли следующий дополнительный код подозрения на Хит? (Именно из кода, включая повторение, за исключением названия были изменены, чтобы защитить невинных)

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X; 

*(volatile UINT16 *)& someVar->something; 

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X; 

*(volatile UINT16 *)& someVar->something; 
x = SomeData; 
+1

Встраиваемый код? Тогда это, вероятно, физический адрес, как подозревается в sharth. –

+0

Примечание. Я добавил ссылку на статью в нижеприведенном ответе: http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt – Artyom

+0

Это хорошая идея, чтобы отличить результат чтения, который никуда не годится с '(void)', чтобы избежать предупреждений компилятора. Итак '(void) * (volatile uint16_t *) & someVar-> something'. Конечно, оберните это макросом или встроенной функцией, не разрезайте и не вставляйте это повсюду! –

ответ

19

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

Так выражение;

*(volatile UINT16 *)&someVar->something; 

выпустит 16 бит для чтения на некотором смещении (обеспечивается something структуры элемент смещения) с адреса сохраняется в someVar указателе. Это чтение будет происходить и не может быть оптимизировано компилятором из-за ключевого слова volatile.

Обратите внимание, что некоторые регистраторы устройств выполняют определенную функциональность, даже если они просто считываются, даже если чтение данных не используется иным образом. Это довольно часто встречается с регистрами состояния, где условие ошибки может быть очищено после считывания регистра, который указывает состояние ошибки в конкретном бите.

Это, вероятно, одна из наиболее распространенных причин использования ключевого слова volatile.

+0

Спасибо, отметили это как ответ, потому что я думаю, что это самый ясный и самый полный ответ. –

9

Я думаю, что намерение автора было заставить компилятор испускать барьеры памяти в этих точках. Оценивая результат выражения volatile, указание на компилятор заключается в том, что это выражение не должно быть оптимизировано и должно «создавать» семантику доступа к неустойчивому местоположению (барьеры памяти, ограничения на оптимизацию) в каждой строке где происходит эта идиома.

Этот тип идиомы может быть «инкапсулирован» в макропроцессоре перед процессором (#define), если другой компилятор имеет другой способ вызвать тот же эффект. Например, компилятор с возможностью прямого кодирования барьеров чтения или записи может использовать встроенный механизм, а не эту идиому. Внедрение этого типа кода внутри макроса позволяет изменить метод по всей вашей базе кода.

EDIT: sharth Пользователь имеет большую точку, что, если этот код работает в среде, где адрес указателя является физического, а не виртуального адреса (или виртуальный адрес отображается на конкретный физический адрес), то выполнение этой операции чтения может вызвать некоторые действия на периферийном устройстве.

+2

Futhermore макрос может сделать его более очевидным, что происходит ... (#define READ_MEMORY_BARRIER ...) – Aaron

+1

Первым шагом должно быть определение того, действительно ли он создает барьер памяти. Это похоже на намерение, но изменчивые переменные на многих платформах упорядочиваются только по отношению к другим изменчивым переменным. Даже если он работает для этой встроенной платформы, он может не работать для другого; Я бы искал лучшее, более портативное решение для создания барьеров. –

+1

Я не понимаю, что это имеет какое-либо отношение к барьерам памяти. Это встроенная платформа, и, вероятно, она отображает переменную в некоторый IO. –

9

Итак, вот длинный снимок.

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

+0

Зачем нужен длинный снимок? Я думаю, что это вполне логичное объяснение. +1 –

+0

В оригинальном вопросе не хватало многих пояснений, которые дают понять, что это происходит во встроенной системе и т. Д. –

-1

Обычно это плохой код.

В C и C++ летучие средства очень мало и не обеспечивают неявного барьера памяти. Таким образом, этот код является просто неправильным, потому что он написан как

memory_barrier(); 
*(volatile UINT16 *)&someVar->something; 

Это просто плохой код.

Expana:volatile не делает переменным атомом!

Рид эта статья: http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt

Вот почему volatile почти никогда не будет использоваться в надлежащем коде.

+2

Eh !? Что это значит? – Clifford

Смежные вопросы