4r45h
4r45h

Reputation: 23

using a struct member as array size in the same struct

I'm new in structured c coding.I don't know if I can define a structure as follows:

typedef struct command_struct {
    uint8_t com_byte_num;
    uint8_t command_bytes[com_byte_num];
    } command;

and use it in another struct:

typedef struct commands_struct {
    command poll_dig;
    command poll_joy;
    command poll_all;
    command enter_config;
    command exit_config;
    command conf_set_analog;
    command conf_set_digital;
    command conf_vib_off;
    command conf_joy_only;
    command conf_joy_press;
} commands;

the uint8_t command_bytes[com_byte_num]; part is what I'm not sure about.

Upvotes: 2

Views: 149

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753585

You can't do the uint8_t command_bytes[com_byte_num]; in standard C — the array size must either be fixed (constant) or you need the notation uint8_t command_bytes[];, which is called a 'flexible array member'.

(However, see another answer about VLAIS — variable-length arrays in a structure. Note, however, that such arrays can only be compiled by GCC, and they can only be defined inside a function, which vastly complicates the process of passing pointers to such structures to other functions.)

If you use a flexible array member, you then cannot create the second structure. You could do it if it contains pointers to the command elements, but not if it contains the actual struct command elements. One of two things will happen:

  1. The compiler complains you can't do it.
  2. The compiler lets you do it, but all the command elements have a zero-size command_bytes member.

Neither is helpful to you. Given the code:

#include <stdint.h>

typedef struct command_struct
{
    uint8_t com_byte_num;
    uint8_t command_bytes[];
} command;

typedef struct commands_struct
{
    command poll_dig;
    command poll_joy;
    command poll_all;
    command enter_config;
    command exit_config;
    command conf_set_analog;
    command conf_set_digital;
    command conf_vib_off;
    command conf_joy_only;
    command conf_joy_press;
} commands;

the command:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c fla.c

compiles the file OK (with GCC 4.8.2 on Mac OS X 10.9.1 Mavericks). If you add -pedantic, then you get a screed of errors such as:

fla.c:11:13: error: invalid use of structure with flexible array member [-Werror=pedantic]
     command poll_dig;

If you change the code as shown below, even the pedantic compilation is happy:

#include <stdint.h>

typedef struct command_struct
{
    uint8_t com_byte_num;
    uint8_t command_bytes[];
} command;

typedef struct commands_struct
{
    command *poll_dig;
    command *poll_joy;
    command *poll_all;
    command *enter_config;
    command *exit_config;
    command *conf_set_analog;
    command *conf_set_digital;
    command *conf_vib_off;
    command *conf_joy_only;
    command *conf_joy_press;
} commands;

Upvotes: 1

user3185968
user3185968

Reputation:

VLAIS (variable-length arrays in structs) is permissible in gcc (and the newest C-standards, I think), but the variable array must always be the last member of the struct (so the compiler knows where all members are...). In partiular this means:
1. There can be only one! (variable-lenght array, that is...)
2. If the struct is a member of another struct, it again has to be the last member of that struct.

Upvotes: 0

Related Questions