Игнорирование проблем дополнения/выравнивания и, учитывая следующую структуру, что лучший способ состоит в том, чтобы получить и установить значение member_b, не используя членское имя.
struct mystruct {
int member_a;
int member_b;
}
struct mystruct *s = malloc(sizeof(struct mystruct));
Другими словами; Как был бы Вы выражать следующее с точки зрения указателей/погашений:
s->member_b = 3;
printf("%i",s->member_b);
Мое предположение к
int
)char
?)int
указатель и набор адрес (к *charpointer + offset
?)int
указатель, чтобы установить содержание памятино я становлюсь немного смущенным кастингом к типу случайной работы или если что-то как memset
более соответствующее или если обычно я - aproching это полностью неправильно.
Аплодисменты для любой помощи
Подход, который вы изложили, примерно правильно, хотя вы должны использовать Offsetof
вместо того, чтобы пытаться выяснить смещение самостоятельно. Я не уверен, почему вы упоминаете MEMSET
- он устанавливает содержимое блока к указанному значению, которое кажется совершенно не связанным с вопросом под рукой.
Вот какой-то код, чтобы продемонстрировать, как он работает:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
typedef struct x {
int member_a;
int member_b;
} x;
int main() {
x *s = malloc(sizeof(x));
char *base;
size_t offset;
int *b;
// initialize both members to known values
s->member_a = 1;
s->member_b = 2;
// get base address
base = (char *)s;
// and the offset to member_b
offset = offsetof(x, member_b);
// Compute address of member_b
b = (int *)(base+offset);
// write to member_b via our pointer
*b = 10;
// print out via name, to show it was changed to new value.
printf("%d\n", s->member_b);
return 0;
}
Полная техника:
Получить смещение с использованием OffsetOf:
b_Offset = Offsetof (Brack mystruct, member_b);
Получить адрес вашей структуры в виде указателя Char * Отказ
CHAR * SC = (CHAR *) S;
Добавьте добавить смещение в адрес структуры, отставьте значение указателю на соответствующий тип и развесел:
* (int *) (SC + b_offset)
Игнорируя обивку и выравнивание, как вы сказали...
Если элементы, на которые вы указываете, полностью одного типа, как в вашем примере, вы можете просто привести структуру к нужному типу и рассматривать ее как массив:
printf("%i", ((int *)(&s))[1]);
Это Звучит от ваших комментариев, что вы действительно делаете, - это упаковка и распаковка куча разрозненных типов данных в один блок памяти. Пока вы могут уйти с тем, что с прямым указателем, поскольку предложили большинство других ответов:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
*(int *)(p + offset) = val;
}
int get_int(void *block, size_t offset)
{
char *p = block;
return *(int *)(p + offset);
}
Проблема в том, что это не портативно. Там нет общего способа для обеспечения того, чтобы типы хранятся в вашем блоке с правильным выравниванием, а некоторые архитектуры просто не могут выполнять нагрузки или хранить в недобросовестные адреса. В частном случае, когда макет вашего блока определяется объявленной структурой, она будет в порядке, поскольку планировка структуры будет включать в себя необходимые прокладки для обеспечения правильного выравнивания. Однако, поскольку вы не можете получить доступ к участникам по имени, звучит так, что это не то, что вы делаете.
Чтобы сделать это портативно, вам необходимо использовать memcpy
:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
memcpy(p + offset, &val, sizeof val);
}
int get_int(void *block, size_t offset)
{
char *p = block;
int val;
memcpy(&val, p + offset, sizeof val);
return val;
}
(аналогично другим типам).
В этом конкретном примере, можно обратиться к нему * ((интервал *) ((символ *) s + sizeof (интервал)))
. Я не уверен, почему вы хотите это, таким образом, я принимаю дидактические цели, поэтому объяснение следует.
бит кода переводит как: взять память, запускающуюся в адресе s, и рассматривать его как память, указывающую символ
. К тому адресу добавьте sizeof (интервал)
символ
- блоки - вы получите новый адрес. Принять значение, что адрес, таким образом созданный и, рассматривает его как интервал
.
Примечание, что запись * (s + sizeof (интервал))
дала бы адрес в s
плюс sizeof (интервал)
sizeof (mystruct) блоки
Редактирование: согласно комментарию Andrey, с помощью offsetof:
* ((интервал *) ((байт *) s + offsetof (структура mystruct, member_b)))
Редактирование 2: Я заменил весь байт
с с символ
с как , sizeof (символ)
, как гарантируют, будет 1.