GCC - Распечатать определение структуры

Может ли программа C распечатать определение структуры? Было бы здорово иметь имена элементов, но было бы достаточно просто упорядоченного списка типов данных (и длины массива в случае массивов).

Я искал директивы препроцессора для достижения этого, но не смог их найти. Существует ли директива препроцессора, которая может захватывать аннотированную часть кода и использовать ее как переменную #define. Если это так, я мог бы инициализировать некоторые переменные sting для хранения значения переменных #define.

Например, такая структура печатается как есть.

struct foo{
int a;
char b;
short arr[6];
}

или вот так

struct s{
int m1;
char m2;
short m3[6];
}

Форматирование не имеет значения, если структуру можно воссоздать из данных. Так что что-то вроде этого тоже хорошо:

s{int,char,short[10]}

Просто к сведению, это устройство на базе ARM с ограниченными ресурсами.

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


person Dojo    schedule 15.10.2016    source источник
comment
Не в стандарте C, насколько я знаю. И определенно не через препроцессор C (под переменной #define вы имеете в виду макрос препроцессора C), поскольку он понятия не имеет, как работает сам C.   -  person    schedule 15.10.2016
comment
@Rhymoid не согласился бы с этим; вы можете использовать препроцессор, чтобы сделать копию рассматриваемого кода для #define structname_code ..., а также создать его экземпляр.   -  person Marcus Müller    schedule 15.10.2016
comment
Я не хочу вручную копировать и вставлять код структуры - вы можете заставить программу читать свой собственный файл исходного кода.   -  person Jongware    schedule 15.10.2016
comment
Это второй @MarcusMüller. Вы можете создавать определения, которые инкапсулируют определения типов и членов, и помещать имена в структуры данных, которые вы оцениваете позже.   -  person Peter - Reinstate Monica    schedule 15.10.2016
comment
Спасибо @MarcusMüller, это должен быть ответ   -  person Dojo    schedule 15.10.2016
comment
@RadLexus Да, в крайнем случае, но если можно использовать существующие механизмы, ничего подобного.   -  person Dojo    schedule 15.10.2016


Ответы (2)


Существуют форматы объектных файлов, которые содержат необходимую информацию и допускают программный доступ. Одним из них является Гном. Отладчики обычно используют эту информацию.

Я не думаю (но и не уверен), что можно получить доступ к отладочной информации для работающего кода. Это отличие от программ на языках, которые выполняются в сложной системе времени выполнения, такой как Java или семейство .net. Те могут использовать рефлексию над собой.

В программах, написанных на традиционно компилируемых языках, вы, вероятно, откроете объектный файл — возможно, сам исполняемый файл! -- и проверить его программно, как это делает отладчик. Учитывая это, можно предположить, что будет проще анализировать исходный код (который в C и C++ должен быть доступен для многих определений типов в виде файлов заголовков). Но для нетривиальных применений эта идея может быть обманчивой, потому что компилятор лексирует и анализирует исходный код для вас и помещает всю информацию в аккуратные структуры данных, где к ним можно легко получить доступ. Эта часть процесса компиляции — то есть значительная часть внешнего интерфейса — должна быть выполнена вами, если вы работаете с исходниками.

person Peter - Reinstate Monica    schedule 15.10.2016

Зачем вам это делать, если у вас уже есть исходный код?

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

Заметьте также, что имена типов, полей и переменных в первую очередь предназначены для придания значения программисту. После компиляции многие имена исчезнут. Только глобальные переменные и отсутствующие внешние переменные сохранят свои имена в объектном файле, чтобы их можно было разрешить во время компоновки, а после компоновки эти имена больше не нужны. Компилятор, например, преобразовал a->b в смещение b относительно места в памяти, где находится a.

person Paul Ogilvie    schedule 15.10.2016
comment
Зачем вам это делать, если у вас уже есть исходный код? У меня есть встроенное устройство IoT. Таких устройств на поле может быть много. Устройство будет отправлять бинарные BLOB-объекты. Эти устройства могут работать под управлением разных версий встроенного ПО, и структура больших двоичных объектов может различаться в зависимости от версии встроенного ПО. Обычный подход заключается в передаче версии микропрограммы и информировании сервера о структурах больших двоичных объектов для каждой версии. Чтобы еще больше усложнить ситуацию, память устройства может содержать данные, сохраненные предыдущими версиями прошивки. Я хотел бы сделать данные самоописательными. - person Dojo; 15.10.2016
comment
Есть обходные пути, не требующие знания структуры. Но они беспорядочны и накладывают ограничения. Мне нравится идея JSON/bJSON. Единственным недостатком этого являются накладные расходы на данные, как только вы заплатите эту цену, вы получите очень гибкую информационную систему, в которой все узлы не должны быть в одной и той же версии для успешного взаимодействия. - person Dojo; 15.10.2016
comment
И причина, по которой я бы не стал вставлять структуру в sprintf, упоминается в самом вопросе. Может быть, в крайнем случае я бы сделал это, но я пытаюсь найти лучшие способы сделать это. Один пользователь на самом деле оставил довольно полезный лайфхак в комментарии. - person Dojo; 15.10.2016
comment
-1, потому что в GCC есть параметр -save-temps, который создает автономный файл, включающий, среди прочего, все структуры, которые он видел во время компиляции. - person Clément; 15.12.2019