3

I am trying to initialize a struct, and assign values to the struct variables.

My struct:

  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;

And when I try to declare and initialize the variable I use the designated initializer:

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

I am using Keil µVision4 and the ARM C compiler for an embedded project. When compiling this code, compiler returns Error #29: Expected an expression. The error occurs on every line in the initialization code.

I read that this is the way to go when writing in ANSI C99, but this doesn't work in my case. How to initialize a struct in ANSI C99

I know i can write the "bad" code:

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

but...

Any tips?


Update: The following code works:

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

But again, this isn't a particulary pretty code or way of doing it.

Community
  • 1
  • 1
Jeffa
  • 123
  • 1
  • 2
  • 7

3 Answers3

1

If you're initializing every thing to 0 just use the universal zero initializer (and ignore any spurious warning the compiler gives you). The universal zero initializer is valid C89, C99, C11 (and I believe it was also valid pre-C89).

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

... I'm sure you get the point


If you want to initialize to values other than 0, and you don't have a C99 compiler, then you need to do it individually, like in your "bad" code.

Or you could separate the parts that need initialization and copy (not initialize) them

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 */
pmg
  • 106,608
  • 13
  • 126
  • 198
  • I'm only initializing it to 0 for now, later in my project I will initialize with values, so a zero initializer will only work for now. I am actually only interested in Kd, Ki and Kp, so its these three values I really need initialized. – Jeffa Aug 07 '12 at 08:57
  • I have never heard of "the universal zero initializer", it is not a well-known term nor does any C standard mention it. While the code you posted is perhaps valid C, the `{0}` initializer should only be used for what the C standard calls "aggregates": arrays, structs and unions, or else you will only confuse the reader. – Lundin Aug 07 '12 at 11:05
  • @Lundin: I kinda agree, but there may be occasions you don't know the exact type and want to initialize anyway: `fpos_t loc = {0}; /* works whether fpos_t is an integer type or some struct */`. The "universal zero initializer" is just the name I learned to refer to `{0}`, not anything from any document. – pmg Aug 07 '12 at 11:27
  • @pmg I don't agree, if you don't know the exact type, it suggests flaws in the program design. If the type is unknown to you because it is an "opaque" (incomplete) type, then the initialization should be inside the routine that knows the type. Ie `fpos_t* loc = fpos_init()` or similar. – Lundin Aug 07 '12 at 11:57
0

The State array should be initialized like:

.State = {0, 0, 0},
Roman Saveljev
  • 2,544
  • 1
  • 21
  • 20
0

by default keil RCVT use C90 standard. If you want to use such syntax for you struct initialization, you may add "--c99" to the compiler option : target options -> C/C++ -> misc contronls.

source keil online support