В соответствующем коде C вы не можете создать статический экземпляр произвольного неизвестного типа, даже если вы знаете его размер во время компиляции (даже если вы не знаете выравнивание).
Допустим, вы пытаетесь сделатьэто все равно.Как бы вы это сделали, учитывая размер в макросе или перечислении PRIVATE_SIZE
?
unsigned char obj[PRIVATE_SIZE];
И тогда вы бы передали (void*)obj
туда, где это необходимо, верно?Ну, это нарушает правила наложения имен.Хотя вы можете легально получить доступ к любому отдельному символу / байту в любом объекте, вы не можете сделать это наоборот, говоря, что эти символы не являются символами, они просто хранятся за другими типами.То есть юридически нельзя накладывать short int
поверх, скажем, obj[2]
и obj[3]
через броски умных штанов (например, ((struct Private*)obj)->my_short = 2;
).Единственный законный способ сделать что-то подобное - через memcpy()
, например memcpy(&temp, obj, sizeof temp);
, а затем обратно после модификации.Или вам нужно работать с отдельными символами obj[]
.
Есть два возможных способа сделать это.Один из них описан в другом ответе, в основном определяют случай, когда тип известен, но только пусть внешний мир имеет указатель на него.
Другой, очень похожий, определяет его в коде сборки и, опять же, пустьвнешний мир имеет указатель на это.«Красота» способа сборки заключается в том, что вам действительно нужно только имя, выравнивание и размер для выделения пространства для именованного объекта.
И если вы помещаете экземпляры в специальный раздел данных (см.Атрибут section gcc и скрипты компоновщика), вы можете даже иметь все экземпляры в одном месте (думать, массив) и даже узнать их совокупный размер и, следовательно, подсчитать.
Еще одна вещь, которую нужно сделать, пока неЯвно нарушая любые правила C, вы все равно должны использовать этот unsigned char obj[PRIVATE_SIZE]
трюк, но отмывать его, передавая его без изменений через функцию сборки, которую компилятор C не может просмотреть, например что-то вроде
// struct Private* launder(unsigned char*);
.text
.globl launder
launder:
move %first_param_reg, %return_reg
ret
Но выВам действительно нужно изменить unsigned char obj[PRIVATE_SIZE]
на что-то, что будет иметь правильное выравнивание в вашей архитектуре, например, double obj[PRIVATE_SIZE / sizeof(double)]
(или то же самое с long long
, если вам так больше нравится).
Что касается PRIVATE_SIZE
, вы можете проверить во время компиляции, что он соответствует размеру типа, например
#include "mod.h" // mod.h defines PRIVATE_SIZE
struct Private { ... };
extern char StAtIcAsSeRt[sizeof(struct Private) == PRIVATE_SIZE];