У меня есть адрес хранилища структур в переменной int. Могу ли я разыменовать структуру??
скажем: int x = 3432234; // адрес памяти структуры теперь я хочу получить доступ к некоторой структуре из него.
Мне предложили эти шаги.
Но не знаю, как подать заявку.
Если вы должны хранить указатель как целое число, используйте intptr_t
или uintptr_t
вместо int
. Но опять же, случаи использования для этого должны быть редкими.
Приведение и разыменование идут вместе естественным образом; например intptr_t x = ... ; struct foo f = *(struct foo *)x; ((struct foo *)x)->y = 42;
и так далее. Или просто используйте переменную временного указателя: struct foo *p = (struct foo *)x; f = *p; p->y = 42;
Почему вы храните указатель в переменной int
? Почему бы не сохранить его в указателе? На 64-битных машинах int
недостаточно велик, чтобы вместить все биты адреса. Сомнительная практика даже на 32-битной машине. Вам нужно будет привести значение к типу указателя, а затем разыменовать его.
Если у вас есть фактический адрес структуры в int
объекте x
и его можно преобразовать обратно в указатель на структуру, то вы можете получить доступ к структуре с помощью ((struct foo *) x)->member
, где struct foo
— имя типа структуры, а member
— имя участника в структуре., или вы можете получить доступ ко всей структуре с помощью * (struct foo *) x
.
Подобные структуры очень часто используются в средах mare metal, поскольку аппаратные регистры часто отображаются в память.
typedef struct
{
volatile uint32_t reg1;
const volatile uint32_t reg2;
}PERIPH1__t;
#define PERIPH1ADDRESS 0x56664550UL
/* OR */
uintptr_t PERIPH1ADDRESS = 0x56664550UL;
#define PERIPH1 ((PERIPH1__t *)PERIPH1ADDRESS)
/* somewhere in the code */
PERIPH1 -> reg1 = 34;
uint32_t reg2val = PERIPH1 -> reg2;
если вы хотите сохранить адрес в целочисленной переменной, лучшим типом будет uintptr_t
, который гарантированно вмещает любой указатель.
int
подписан и во многих системах недостаточно велик для хранения адресов — например, 64-битные системы часто имеют 64-битные адреса и только 32-битные целые числа.
Конечно, но обычно вы не храните PERIPH1ADDRESS
в переменной int
.
Если у вас есть struct foo
, проще всего не использовать int x
, а сделать тип указателем на struct foo
, struct foo *x
. Можно использовать оператор стрелки для прямого доступа к членам из действительного указателя.
#include <stdio.h>
struct foo { int a, b; };
int main(void) {
struct foo foo = { 1, 2 };
struct foo *x = &foo;
printf("%d, %d\n", x->a, x->b);
}
Иногда это усложняют требования к оборудованию, но это простое решение.
Обычно небезопасно приводить указатель к
int
и обратно; вы не можете быть уверены, что это действительно, когда вы закончите. Например, во многих системахint
меньше указателя, поэтому биты обязательно будут потеряны. Почему вы хотите это сделать?