Вложенная структура и простая структура в памяти с теми же данными?

#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, чтобы отключить заполнение. В конце концов, просто воздержитесь от очень странных действий: если вы хотите «ввести каламбур» между двумя структурами, затем поместите их в один и тот же союз, точка.