C struct указатель шаг от первого до последнего элемента


Обеспечение структурного теста:

#include <stdio.h>

int main() {

   struct {
      char* one;
      char* two;
      char* three;
    } test;

    char **ptr = &test.one;
    *ptr = "one";
    *++ptr = "two";
    *++ptr = "three";

    printf ("%sn", test.one);
    printf ("%sn", test.two);
    printf ("%sn", test.three);
}
Вопрос: есть ли гарантия, что элементы в структуре test всегда находятся в последовательном порядке памяти? (Таким образом, начиная с первого элемента структуры ++ptr всегда будет указывать на следующий элемент в структуре test?)
2 2

2 ответа:

Как отмечено в комментарии к вопросу:

Да; элементы структуры хранятся в том порядке, в котором они объявлены. Что может расстроить расчеты, так это то, что между элементами могут быть пробелы (отступы). Этого не произойдет, когда все они будут одного типа.

однако , Вы должны спросить себя: если мне нужно последовательно пройти через элементы, почему я не использую массив? Массивы предназначены для последовательного доступа; структуры-нет (и написание кода для доступ к элементам структуры последовательно является беспорядочным).

Некоторые соответствующие части стандарта таковы:

§6.7.2.1 структура и Союза проектировщиков

Как обсуждалось в 6.2.5, структура - это тип, состоящий из последовательности членов, которые хранилище выделяется в упорядоченной последовательности, а объединение-это тип, состоящий из последовательности членов, чьи хранилища перекрываются.

¶15 внутри объекта структуры члены не-битового поля и единицы измерения в которых битовые поля адреса резидентов увеличиваются в том порядке, в котором они объявлены. Указатель на a объект структуры, соответствующим образом преобразованный, указывает на его исходный элемент (или если этот элемент является бит-поле, то к единице, в которой оно находится), и наоборот. Там могут быть неназванные заполнение внутри объекта структуры, но не в его начале.

§6.2.5 типы

¶20 ...

  • тип структуры описывает последовательно выделенный непустой набор объектов-членов (и, при определенных обстоятельствах, неполный массив), каждый из которых имеет необязательный указанное имя и, возможно, отдельный тип.

Для указателей, скорее всего, вы всегда будете наблюдать такое поведение, но единственная гарантия, которую дает язык C, - это то, что элементы упорядочены в памяти. Между ними могут быть промежутки для оптимизации выравнивания полей (для производительности, особенно на архитектурах RISC).

Правильный способ сделать это-использовать макрос offsetof или сделать его массивом.