Как я могу получить доступ к полям структуры по имени во время выполнения? - PullRequest
3 голосов
/ 25 марта 2010

Часто задаваемые вопросы C объясняют это в некотором смысле, вот ссылка.

Но я не могу этого понять, Кто-нибудь может объяснить это для меня? Или дать мне другой способ?

Большое спасибо!

Ответы [ 5 ]

6 голосов
/ 25 марта 2010

Я думаю, этот пример проясняет ответ:

struct test
{
    int b;
    int a;
};

int main() 
{
    test t;
    test* structp = &t;

    //Find the byte offset of 'a' within the structure
    int offsetf = offsetof(test, a);

    //Set the value of 'a' using pointer arithmetic
    *(int *)((char *)structp + offsetf) = 5;

    return 0;

}
1 голос
/ 25 марта 2010

Если ваш двоичный файл скомпилирован с отладочной информацией, вы можете использовать его для поиска имен во время выполнения. Например, gcc (обычно) создает отладочную информацию в формате DWARF , и вы можете использовать libdwarf для ее обработки.

В случае DWARF вы можете найти свое поле в узле DW_TAG_member, атрибут DW_AT_data_member_location даст вам смещение поля, такое же, как вы получаете от offsetof() во время компиляции.

1 голос
/ 25 марта 2010

Вы не можете, не реализовав какой-либо поиск имени самостоятельно.

C не имеет никакого времени для информации об имени, когда программа запущена.

Сложно поддерживать это обычно для различных типов структурных полей.

0 голосов
/ 18 июня 2013

Если структура определена с использованием определения struct {...}, маловероятно, что в исполняемом коде будет какая-либо информация, связанная с именами элементов. Некоторые платформы встраивают «отладочную» информацию в сгенерированные исполняемые файлы, и могут быть какие-то средства, с помощью которых работающая программа может получить эту информацию, но нет общего способа сделать такие вещи.

Однако можно уметь использовать макросы для определения структуры. Например, можно определить:

#define MAKE_ACME_STRUCT \
  FIELD(id,int,23) \
  X FIELD(name,char30,"Untitled") \
  X FIELD(info,int,19) \
  // LEAVE THIS COMMENT HERE

, а затем вызывать макрос MAKE_ACME_STRUCT несколько раз, причем макросы FIELD и X определены различными способами, так что он будет расширяться либо до оператора структуры, либо из выражения инициализации для экземпляра этой структуры по умолчанию или как выражение инициализации для массива элементов, описывающих поля структуры [например, что-то вроде

STRUCT_INFO acme_struct_info[] = {
  {"id", STRUCT_INFO_TYPE_int, sizeof(ACME_STRUCT.id), offsetof(ACME_STRUCT.id)}
  ,{"name", STRUCT_INFO_TYPE_char30, sizeof(ACME_STRUCT.name), offsetof(ACME_STRUCT.name)}
  ,{"info", STRUCT_INFO_TYPE_int, sizeof(ACME_STRUCT.info), offsetof(ACME_STRUCT.info)}
  ,{0}};

Было бы необходимо, чтобы все типы, используемые в структуре, имели имена с одним токеном и чтобы для каждого такого имени был определен идентификатор STRUCT_INFO_TYPE_nameGoesHere, который идентифицирует тип для библиотеки времени выполнения в некоторой форме, которую он понимает. .

Такие макросы вряд ли прекрасны, но они имеют преимущество в том, что все вещи, которые они используют для определения, остаются синхронизированными [например, гарантируя, что добавление или удаление элемента acme_struct приведет к его добавлению или удалению из списка членов структуры, хранящегося в acme_struct_info].

0 голосов
/ 18 июня 2013

Отслеживание смещений полей, вычисленных с помощью макроса offsetof (). Если structp является указателем на экземпляр структуры, а поле f является int, имеющим смещение offsetf, значение f может быть установлено косвенно с помощью

*(int *)((char *)structp + offsetf) = value;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...