Разница между (*(volatile unsigned int *) и (volatile unsigned int)?

Я просматривал учебные пособия по программированию STM32 без операционной системы. Я не мог понять назначение приведенного ниже кода

 #define RCC_AHB1EN_R (*(volatile unsigned int *)(RCC_BASE + AHB1EN_R_OFFSET))

и почему это отличается от

#define RCC_AHB1EN_R (volatile unsigned int)(RCC_BASE + AHB1EN_R_OFFSET))

Я понимаю, что (volatile unsigned int *) используется для приведения любых данных к типу, поэтому код получает значение своего адреса, а не сами данные, а затем добавляет (*) выберет значение данных адреса. Я знаю, почему volatile используется, чтобы запретить оптимизировать этот код для этих данных.

Это мои базовые знания об указателях, если я до сих пор был не прав, поправьте меня.

Итак, мой вопрос:

  1. Почему и какова цель приведения данных к адресу (указателю), а затем использовать его значение?

  2. Почему бы нам не использовать само значение напрямую (конечно, с изменчивым приведением типов), например

#define RCC_AHB1EN_R (изменчивое целое число без знака)(RCC_BASE + AHB1EN_R_OFFSET))

  1. Если мы можем использовать все, что можем, есть ли преимущества у одного перед другим?

, 👍1


2 ответа


Лучший ответ:

2

Судя по контексту, RCC_BASE выглядит как макрос препроцессора. который расширяется до базового адреса некоторого периферийного устройства, называемого «RCC», и AHB1EN_R_OFFSET аналогичный макрос для смещения ввода-вывода AHB1EN_R зарегистрироваться относительно этого базового адреса. Затем

RCC_BASE + AHB1EN_R_OFFSET

— отображаемый в памяти адрес регистра. Этот адрес просто число. Если вы приведете его к volatile unsigned int, вы все равно получите такое же количество. Если вы хотите получить доступ к регистру ввода-вывода, вы должны сказать компилятору, что это число на самом деле является адресом (т.е. числовым значение указателя), а затем получить доступ к шине памяти по этому адресу (т.е. разыменовать указатель):

  • (volatile unsigned int *) преобразует числовое значение в указатель (из-за *), который указывает на volatile unsigned int

  • * в начале макроса разыменовывает указатель и, таким образом, выполняет фактический доступ к регистру ввода/вывода.

,

Хорошо, пожалуйста, скажи мне, правильно ли я понял. (*(volatile unsigned int *)(RCC_BASE + AHB1EN_R_OFFSET)) заставит (RCC_BASE + AHB1EN_R_OFFSET) считаться адресом и получит значение по этому адресу, так как перед ним стоит *. Но то, что я понимаю из использования volatile, говорит компилятору не оптимизировать значение переменной. Я запутался с volatile с указателем. Таким образом, даже в этом случае 'volatile' дается для значения, хранящегося по этому адресу, а не само *значение адреса*?, @Just doin Gods work

@JustdoinGodswork: Действительно. Такое объявление, как TYPE * volatile p;, сделает p изменчивым указателем, тогда как volatile TYPE *p; делает p указателем на изменчивые данные. Состав, который мы видим здесь, соответствует более позднему объявлению., @Edgar Bonet


1

В первой строке RCC_AHB1EN_R — это указатель на местоположение. вы получили это от кастинга.

#define RCC_AHB1EN_R (*(изменчивое целое число без знака *)(RCC_BASE + AHB1EN_R_OFFSET))

Во второй строке RCC_AHB1EN_R содержит базовый адрес, который является целым числом.

#define RCC_AHB1EN_R (изменчивое целое без знака)(RCC_BASE + AHB1EN_R_OFFSET))

надеюсь, это внесет ясность?

,