Является ли разыменование в c ++ lvalue или rvalue?

Я уверен, что понимаю смысл rvalue а также lvalue, Что мне не ясно, так это разыменование rvalue,

Учти это:

#define GPIO_BASE             0x20200000
#define GPFSEL1               (*(volatile unsigned int *)(AUX_MU_BASE + 0x4))

GPFSEL1 — это разыменование беззнакового указателя int. Указатель int без знака является физическим адресом аппаратного регистра.

Я читал, что это обычная техника в программировании на голом железе для прямого доступа к аппаратным регистрам. Пока что я могу использовать его без проблем.

Теперь я хочу reference в GPFSEL1 как член структуры. Это возможно?

struct MotorControl
{
u8 pwm_pin;
u8 ctrla_pin;
u8 ctrlb_pin;
volatile unsigned int* MYGPFSEL; // this is not the same thing so does not work
}

Учитывая эту функцию ниже, что является правильным способом ссылки GPFSEL1 который определен в другом месте и как разыменовать его, чтобы установить его значение?

MotorContorl group
group.MYGPFSEL = ?
void set(unsigned char pin_number, bool high)
{
if (high)
{
// how to correct this statement
group.MYGPFSEL |= 1<< pin_number;
}
}

2

Решение

«Разыменование» — это глагол — вы разыменовываете указатель, чтобы получить доступ к значению, на которое он указывает.

Преобразование типов является простым — если у вас есть указатель на целое число, и вы разыменовываете его, теперь вы работаете с целым числом. Это lvalue, так как он (по построению) занимает место в памяти, и его можно (обычно) изменить.

int x = 10;
int* xptr = &x;
*xptr = 5; // *xptr is an lvalue
std::cout << "X: " << x << std::endl; // Prints 5

Однако указатель должен указывать на место в памяти. Если вы только начнете с

int* xptr;
*xptr = 5;

Вы получите ошибку, так как вы пытаетесь разыменовать указатель, который не указывает на действительный адрес памяти. (И если это произойдет, это просто совпадение, и вы неверно измените значение.)

Если вам нужна ссылка на GPFSEL1 в качестве члена вашей структуры MotorControl, вы не сможете инициализировать структуру, не передав ей объект, на который она будет ссылаться. Вместо этого вы, вероятно, захотите указатель внутри структуры, с которым гораздо проще работать:

MotorControl myMotorControl;
myMotorControl.MYGPFSEL = GPFSELF1;
3

Другие решения

Ваш текущий подход будет работать нормально, вам просто нужно правильно инициализировать переменную-член, например,

struct MotorControl control;
control.MYGPFSEL = (volatile unsigned int *)(AUX_MU_BASE + 0x4);

в качестве альтернативы вы можете инициализировать его как

control = &GPFSEL1;

учитывая, что вы определили GPFSEL1, как в исходном вопросе:

#define GPFSEL1 (*(volatile unsigned int *)(AUX_MU_BASE + 0x4))`

Теперь вы можете прочитать реестр:

 foo = *control.MyGPFSEL;

или установите регистр:

 *control.MyGPFSEL = 123;
1

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

Простой случай для иллюстрации:

char sz[] {"hello"};
*sz = 'j';

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

-2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector