2013-09-18 3 views
0

Здесь представлена ​​упрощенная версия двух структур у меня есть:статический инициализатор массива во время инициализации структуры

struct MyStruct1 { 
    double d; 
} 

struct MyStruct2 { 
    struct MyStruct1* a; 
    int i; 
} 

можно инициализировать второй-структуру следующим образом:

void InitStruct(struct MyStruct2 pMyStruct2) { 
    static struct MyStruct1 A[] = { {.d=12} , {.d=17} , {.d=1} }; 
    *pMyStruct2 = (struct MyStruct2) { .a = A, .i = 3 }; 
} 

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

void InitStruct(struct MyStruct2 pMyStruct2) { 
    *pMyStruct2 = (struct MyStruct2) { 
     .a = (struct MyStruct1[]) { 
      {.d=12} , {.d=17} , {.d=1}}, 
     .i=3 }; 
} 

Оба способа компилируются без каких-либо предупреждений , но данные во втором решении повреждаются.

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

Есть ли другой способ сообщить компилятору сохранить данные массива в памяти?

+1

Данные не должны быть повреждены. В этом случае 'static' относится к привязке, а не к длительности хранения. Вы уверены, что вы не упрощаете что-то важное? – cnicutar

+2

Где именно объявляется 'b'? Можете ли вы опубликовать небольшую программу, которая представляет проблему? – hmjd

+0

Являются ли объявления на уровне файла или функцией/блоком? – Gauthier

ответ

1

C99 standard §6.5.2.5 р6 говорит, что:

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

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

Если вы, однако, вернете структуру из функции по значению, указатель станет недействительным.

Вот пример кода, который я использовал для тестирования. Valgrind не отображает ошибок.

#include <stdio.h> 

struct MyStruct1 { 
    double d; 
}; 

struct MyStruct2 { 
    struct MyStruct1* a; 
    int i; 
}; 

struct MyStruct1 A[] = { {.d=12} , {.d=17} , {.d=1} }; 
struct MyStruct2 b1 = { .a = A, .i = 3 }; 

struct MyStruct2 b2 = { .a = (struct MyStruct1[]) { 
           {.d=12} , {.d=17} , {.d=1} 
          }, 
         .i=3 }; 



int main(void) { 
    struct MyStruct1 B[] = { {.d=12} , {.d=17} , {.d=1} }; 
    struct MyStruct2 b3 = { .a = B, .i = 3 }; 

    struct MyStruct2 b4 = { .a = (struct MyStruct1[]) { 
           {.d=12} , {.d=17} , {.d=1} 
          }, 
          .i=3 }; 

    printf("b1->a.d=%1.2f\n", b1.a->d); 
    printf("b2->a.d=%1.2f\n", b2.a->d); 

    printf("b3->a.d=%1.2f\n", b3.a->d); 
    printf("b4->a.d=%1.2f\n", b4.a->d); 

} 
+0

«Блокировка блока» будет областью, которая включает объявление, а не само декларацию (только потому, что список инициализаторов использует фигурные скобки, не делает его «закрывающим блоком»). I.e., если вы объявляете в функции вне блока, внутренняя структура будет локальной переменной. Но +1 для цитаты. – delicateLatticeworkFever

+0

@ goldilocks, спасибо, ты прав, я отредактировал свой ответ. – Dariusz

Смежные вопросы