#c
#c
Вопрос:
Учитывая три следующие структуры (в любой архитектуре 16 бит или выше) :
typedef struct {
int a;
char b;
float c;
char d;
int e[10];
} StructA;
typedef struct {
int a;
char b;
float c;
char d;
} StructB;
typedef struct {
StructB sb;
int e[10];
} StructC;
Затем я объявляю :
StructA sa;
StructC sc;
Давайте предположим невозможный факт, что sa и sc указывают на один и тот же адрес для целей сравнения.
Я понял, что sa, sa.a, sc, sc.sb и sc.sb.a будет использовать один и тот же адрес, учитывая (невозможное) вышеуказанное условие.
Мой вопрос: учитывая, что sa и sc начинаются с одного и того же адреса, могу ли я считать само собой разумеющимся, что sa.e и sc.e также начинаются с одного и того же адреса, если структура является непрерывной в памяти (но заполняется)? Может ли заполнение помешать моему предположению? Будет ли допустимым использование memcpy для sa в sc?
Комментарии:
1. вы могли бы поместить обе структуры в объединение, чтобы заставить их совместно использовать адрес
union { structA sa; structC sc; } u;
Ответ №1:
Модель памяти C является несколько высокоуровневой и предполагает, что все объекты (переменные) в памяти имеют тип, называемый эффективным типом. Если вам каким-то образом удастся выделить sa
и sc
использовать один и тот же адрес с помощью некоторых приемов компоновщика, вы делаете вещи, выходящие за рамки языка C. И поэтому никакое поведение не гарантируется, это может сбить с толку компилятор, и это неопределенное поведение.
Если бы вы выделили две структуры по одному и тому же адресу с помощью using union
, это была бы другая история. Однако в таком случае каждая отдельная структура все равно будет использовать заполнение, поэтому нет никаких гарантий, если вы точно не знаете, как заполняется каждая структура. Если бы каждая структура была членом одного и того же объединения, вы могли бы безопасно выполнять обмен данными между ними, используя sizeof
объединение, даже если один член объединения меньше другого.
Комментарии:
1. Извините, что ввел вас в заблуждение, я уточню. Дело не в том, чтобы заставить sa и sc использовать один и тот же адрес, я сделал предположение для простого сравнения адресов. В реальности у них, конечно, был бы другой адрес, и я хочу знать, является ли их выравнивание памяти в конце идентичным. Если вам нужен более релевантный пример, представьте, что программное обеспечение 1 отправляет struct StructA как, скажем, массив байтов, а программное обеспечение 2 получает его и анализирует массив байтов как StructC . Это сработает?
2. @Kinxil Ну, в принципе, язык не дает никаких гарантий. Могут быть гарантии со стороны конкретного компилятора, но написание кода, полагающегося на это, непереносимо. Вы могли бы использовать нестандартные приемы, такие как #pragma pack, чтобы отключить заполнение. В конце концов, просто воздержитесь от очень странных действий: если вы хотите «ввести каламбур» между двумя структурами, затем поместите их в один и тот же союз, точка.