У меня есть адрес памяти хранилища структуры в переменной int. Могу ли я разыменовать структуру, используя это значение int в C?

У меня есть адрес хранилища структур в переменной int. Могу ли я разыменовать структуру??

скажем: int x = 3432234; // адрес памяти структуры теперь я хочу получить доступ к некоторой структуре из него.

Мне предложили эти шаги.

  1. сохранить адрес в переменной int
  2. приведите это к указателю структуры
  3. затем разыменуйте его

Но не знаю, как подать заявку.

Обычно небезопасно приводить указатель к int и обратно; вы не можете быть уверены, что это действительно, когда вы закончите. Например, во многих системах int меньше указателя, поэтому биты обязательно будут потеряны. Почему вы хотите это сделать?

Nate Eldredge 12.11.2022 19:42

Если вы должны хранить указатель как целое число, используйте intptr_t или uintptr_t вместо int. Но опять же, случаи использования для этого должны быть редкими.

Nate Eldredge 12.11.2022 19:44

Приведение и разыменование идут вместе естественным образом; например 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;

Nate Eldredge 12.11.2022 19:46

Почему вы храните указатель в переменной int? Почему бы не сохранить его в указателе? На 64-битных машинах int недостаточно велик, чтобы вместить все биты адреса. Сомнительная практика даже на 32-битной машине. Вам нужно будет привести значение к типу указателя, а затем разыменовать его.

Jonathan Leffler 12.11.2022 19:46

Если у вас есть фактический адрес структуры в int объекте x и его можно преобразовать обратно в указатель на структуру, то вы можете получить доступ к структуре с помощью ((struct foo *) x)->member, где struct foo — имя типа структуры, а member — имя участника в структуре., или вы можете получить доступ ко всей структуре с помощью * (struct foo *) x.

Eric Postpischil 12.11.2022 19:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Подобные структуры очень часто используются в средах 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.

Nate Eldredge 12.11.2022 20:23
Ответ принят как подходящий

Если у вас есть 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);
}

Иногда это усложняют требования к оборудованию, но это простое решение.

Другие вопросы по теме