Инициализация структуры с использованием назначенного инициализатора во встроенном C. Ожидается выражение

Я пытаюсь инициализировать структуру и присвоить значения переменным структуры.

Моя структура:

  typedef struct 
  {
    q31_t A0;
    q31_t A1;
    q31_t A2;
    q31_t State[3];
    q31_t Kp;
    q31_t Ki;
    q31_t Kd;
   } arm_pid_instance_q31;

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

arm_pid_instance_q31 pitch_pid_instance
={
  .A0 = 0,
  .A1 = 0,
  .A2 = 0,
  .State ={0,0,0},
  .Kd = 0, 
  .Ki = 0, 
  .Kp = 0 
 };

Я использую Keil µVision4 и компилятор ARM C для встроенного проекта. При компиляции этого кода компилятор возвращает Ошибка №29: Ожидается выражение. Ошибка возникает в каждой строке кода инициализации.

Я читал, что это способ писать в ANSI C99, но в моем случае это не работает. Как инициализировать структуру в ANSI C99

Я знаю, что могу написать "плохой" код:

 arm_pid_instance_q31 pitch_pid_instance;
   pitch_pid_instance.A0 = 0; 
   etc...

но...

Какие-нибудь советы?


Обновление: работает следующий код:

  arm_pid_instance_q31 pitch_pid_instance = {0,0,0,0,0,0,0,0,0};

Но опять же, это не особенно красивый код или способ сделать это.


person Jeffa    schedule 07.08.2012    source источник
comment
вы компилируете компилятором, совместимым с c99?   -  person tbert    schedule 07.08.2012
comment
Кстати, кастинг будет работать: Foo foo = (Foo){ .x = y, .., .. };   -  person c00kiemon5ter    schedule 07.08.2012
comment
@ c00kiemon5ter Это не кастинг.   -  person cnicutar    schedule 07.08.2012
comment
@cnicutar верно, это просто похожая схема, но я не могу вспомнить правильное слово банкомат: / пожалуйста, поправьте меня   -  person c00kiemon5ter    schedule 07.08.2012
comment
Я не думаю, что MDK-ARM совместим с c99.   -  person Jeffa    schedule 07.08.2012
comment
@ c00kiemon5ter Назначенные инициализаторы. К кастингу отношения не имеет.   -  person cnicutar    schedule 07.08.2012


Ответы (3)


Если вы инициализируете каждую вещь 0, просто используйте универсальный нулевой инициализатор (и игнорируйте любые ложные предупреждения, которые дает вам компилятор). Универсальный нулевой инициализатор действителен для C89, C99, C11 (и я полагаю, что он также был действителен до C89).

arm_pid_instance_q31 pitch_pid_instance = {0};
struct somecomplexstruct array[1000] = {0};

... Я уверен, что вы поняли


Если вы хотите инициализировать значения, отличные от 0, и у вас нет компилятора C99, вам нужно сделать это индивидуально, как в вашем «плохом» коде.

Или вы можете отделить части, требующие инициализации, и скопировать (не инициализировать) их.

struct substruct {
    q31_t Kp;
    q31_t Ki;
    q31_t Kd;
};
struct arm_pid_instance_q31 {
    q31_t A0;
    q31_t A1;
    q31_t A2;
    q31_t State[3];
    struct substruct K;
};

struct substruct tmp = {42, -1, -1000};
struct arm_pid_instance_q31 pitch_pid_instance; /* uninitialized */
memcpy(&pitch_pid_instance.K, &tmp, sizeof tmp); /* copy values */
person pmg    schedule 07.08.2012
comment
Сейчас я только инициализирую его значением 0, позже в моем проекте я инициализирую значениями, поэтому нулевой инициализатор будет работать только сейчас. На самом деле меня интересуют только Kd, Ki и Kp, поэтому эти три значения мне действительно нужно инициализировать. - person Jeffa; 07.08.2012
comment
Я никогда не слышал об универсальном нулевом инициализаторе, это малоизвестный термин, и он не упоминается ни в одном стандарте C. Хотя код, который вы разместили, возможно, является допустимым C, инициализатор {0} следует использовать только для того, что стандарт C называет агрегатами: массивы, структуры и объединения, иначе вы только запутаете читателя. - person Lundin; 07.08.2012
comment
@Lundin: Я согласен, но могут быть случаи, когда вы не знаете точный тип и все равно хотите инициализировать: fpos_t loc = {0}; /* works whether fpos_t is an integer type or some struct */. Универсальный нулевой инициализатор — это просто имя, которое я узнал для обозначения {0}, а не что-то из какого-либо документа. - person pmg; 07.08.2012
comment
@pmg Я не согласен, если вы не знаете точный тип, это говорит о недостатках в дизайне программы. Если тип вам неизвестен, потому что это непрозрачный (неполный) тип, тогда инициализация должна быть внутри подпрограммы, которая знает этот тип. Т.е. fpos_t* loc = fpos_init() или подобное. - person Lundin; 07.08.2012

Массив State должен быть инициализирован следующим образом:

.State = {0, 0, 0},
person Roman Saveljev    schedule 07.08.2012

по умолчанию keil RCVT использует стандарт C90. Если вы хотите использовать такой синтаксис для инициализации вашей структуры, вы можете добавить "--c99" в параметр компилятора: целевые параметры -> C/C++ -> разное управление.

источник онлайн-поддержки keil

person Selso Liberado    schedule 26.03.2014