Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Can I put a variable length array inside a struct somehow?

Can I put a variable length array inside a struct somehow?

Scheduled Pinned Locked Moved C / C++ / MFC
hardwaredata-structuresquestion
15 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    arnold_w
    wrote on last edited by
    #1

    I am working with an embedded microcontroller (ARM) and I'm building with GCC. The following is fully possible for me to:

    struct testStruct_s {
    int dummy;
    const char* string;
    };

    struct testStruct_s testStructArray[] = {
    {0, "Hello World"},
    {0, "Hello World Again"}
    };

    But why isn't the following possble?

    struct testStruct_s {
    int dummy;
    int* array;
    };

    struct testStruct_s testStructArray[] = {
    {0, {0, 1, 2, 3}},
    {0, {0, 1, 2, 3, 4}}
    };

    Is there a workaround to achieve this? I do not want to specify the array values outside the struct so the following is not what I want:

    int array1[] = {0, 1, 2, 3};
    int array2[] = {0, 1, 2, 3, 4};

    struct testStruct_s testStructArray[] = {
    {0, array1},
    {0, array2}
    };

    P CPalliniC J 3 Replies Last reply
    0
    • A arnold_w

      I am working with an embedded microcontroller (ARM) and I'm building with GCC. The following is fully possible for me to:

      struct testStruct_s {
      int dummy;
      const char* string;
      };

      struct testStruct_s testStructArray[] = {
      {0, "Hello World"},
      {0, "Hello World Again"}
      };

      But why isn't the following possble?

      struct testStruct_s {
      int dummy;
      int* array;
      };

      struct testStruct_s testStructArray[] = {
      {0, {0, 1, 2, 3}},
      {0, {0, 1, 2, 3, 4}}
      };

      Is there a workaround to achieve this? I do not want to specify the array values outside the struct so the following is not what I want:

      int array1[] = {0, 1, 2, 3};
      int array2[] = {0, 1, 2, 3, 4};

      struct testStruct_s testStructArray[] = {
      {0, array1},
      {0, array2}
      };

      P Offline
      P Offline
      Peter_in_2780
      wrote on last edited by
      #2

      In your first example, the struct member is a char *, that is, a pointer. Its size is fixed, although the string it points to (which is stored elsewhere) may be of variable size. A debugger will show you what lives where at run time.

      Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012

      A 1 Reply Last reply
      0
      • P Peter_in_2780

        In your first example, the struct member is a char *, that is, a pointer. Its size is fixed, although the string it points to (which is stored elsewhere) may be of variable size. A debugger will show you what lives where at run time.

        Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012

        A Offline
        A Offline
        arnold_w
        wrote on last edited by
        #3

        Yes, char* is a pointer. But I believe int*, in the second example, is also a pointer.

        P 1 Reply Last reply
        0
        • A arnold_w

          Yes, char* is a pointer. But I believe int*, in the second example, is also a pointer.

          P Offline
          P Offline
          Peter_in_2780
          wrote on last edited by
          #4

          (1, 2, 3} is 3 int's. It is not a pointer to an array of 3 int's. The string/char * fudge dates from the early days of C before they realised they needed string as a first class data type.

          Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012

          1 Reply Last reply
          0
          • A arnold_w

            I am working with an embedded microcontroller (ARM) and I'm building with GCC. The following is fully possible for me to:

            struct testStruct_s {
            int dummy;
            const char* string;
            };

            struct testStruct_s testStructArray[] = {
            {0, "Hello World"},
            {0, "Hello World Again"}
            };

            But why isn't the following possble?

            struct testStruct_s {
            int dummy;
            int* array;
            };

            struct testStruct_s testStructArray[] = {
            {0, {0, 1, 2, 3}},
            {0, {0, 1, 2, 3, 4}}
            };

            Is there a workaround to achieve this? I do not want to specify the array values outside the struct so the following is not what I want:

            int array1[] = {0, 1, 2, 3};
            int array2[] = {0, 1, 2, 3, 4};

            struct testStruct_s testStructArray[] = {
            {0, array1},
            {0, array2}
            };

            CPalliniC Online
            CPalliniC Online
            CPallini
            wrote on last edited by
            #5

            Using 'compound literals[^]', you can:

            #include

            struct testStruct_s {
            int dummy;
            int* array;
            };

            struct testStruct_s testStructArray[] = {
            { 0, (int[]){0, 1, 2, 3, -1}},
            { 0, (int[]){0, 1, 2, 3, 4, -1}}
            };

            int main()
            {
            for (int i=0; i

            In testa che avete, signor di Ceprano?

            A 1 Reply Last reply
            0
            • CPalliniC CPallini

              Using 'compound literals[^]', you can:

              #include

              struct testStruct_s {
              int dummy;
              int* array;
              };

              struct testStruct_s testStructArray[] = {
              { 0, (int[]){0, 1, 2, 3, -1}},
              { 0, (int[]){0, 1, 2, 3, 4, -1}}
              };

              int main()
              {
              for (int i=0; i

              A Offline
              A Offline
              arnold_w
              wrote on last edited by
              #6

              Is this a compiler-specific feature or is it part of standard C? And is there a way that I can obtain the size of the arrays? The following simply returns the size of the pointer, not the array:

              sizeof(testStructArray[0].array)

              CPalliniC 1 Reply Last reply
              0
              • A arnold_w

                Is this a compiler-specific feature or is it part of standard C? And is there a way that I can obtain the size of the arrays? The following simply returns the size of the pointer, not the array:

                sizeof(testStructArray[0].array)

                CPalliniC Online
                CPalliniC Online
                CPallini
                wrote on last edited by
                #7

                I report you the first sentence of the linked page:

                ISO C99 supports compound literals. A compound literal looks like a cast containing an initializer. Its value is an object of the type specified in the cast, containing the elements specified in the initializer; it is an lvalue. As an extension, GCC supports compound literals in C89 mode and in C++.

                So:

                • C99 compilers support it.
                • Your compiler suopports it even in C89 mode.

                In testa che avete, signor di Ceprano?

                A 1 Reply Last reply
                0
                • CPalliniC CPallini

                  I report you the first sentence of the linked page:

                  ISO C99 supports compound literals. A compound literal looks like a cast containing an initializer. Its value is an object of the type specified in the cast, containing the elements specified in the initializer; it is an lvalue. As an extension, GCC supports compound literals in C89 mode and in C++.

                  So:

                  • C99 compilers support it.
                  • Your compiler suopports it even in C89 mode.
                  A Offline
                  A Offline
                  arnold_w
                  wrote on last edited by
                  #8

                  Unfortunately I have very little knowledge about compilers and I don't know what C89 and C99 are. What I'm worried about is that my code won't compile in the future if we move to a different compiler.

                  CPalliniC L 2 Replies Last reply
                  0
                  • A arnold_w

                    Unfortunately I have very little knowledge about compilers and I don't know what C89 and C99 are. What I'm worried about is that my code won't compile in the future if we move to a different compiler.

                    CPalliniC Online
                    CPalliniC Online
                    CPallini
                    wrote on last edited by
                    #9

                    Quote:

                    Unfortunately I have very little knowledge about compilers and I don't know what C89 and C99 are

                    It's time to learn, then.

                    Quote:

                    What I'm worried about is that my code won't compile in the future if we move to a different compiler

                    If you are really worried about then don't use the feature. You might also check in advance if the compiler you are planning to use in future supports such a feature (or, generally C99 features).

                    In testa che avete, signor di Ceprano?

                    J 1 Reply Last reply
                    0
                    • A arnold_w

                      Unfortunately I have very little knowledge about compilers and I don't know what C89 and C99 are. What I'm worried about is that my code won't compile in the future if we move to a different compiler.

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #10

                      Then it is easy enough to make your code simpler:

                      struct testStruct_s {
                      int dummy;
                      int* array;
                      };

                      int array1[] = {0, 1, 2, 3};
                      int array2[] = {0, 1, 2, 3, 4};
                      struct testStruct_s testStructArray[] = {
                      {0, array1},
                      {0, array2}
                      };

                      A 1 Reply Last reply
                      0
                      • CPalliniC CPallini

                        Quote:

                        Unfortunately I have very little knowledge about compilers and I don't know what C89 and C99 are

                        It's time to learn, then.

                        Quote:

                        What I'm worried about is that my code won't compile in the future if we move to a different compiler

                        If you are really worried about then don't use the feature. You might also check in advance if the compiler you are planning to use in future supports such a feature (or, generally C99 features).

                        J Offline
                        J Offline
                        jschell
                        wrote on last edited by
                        #11

                        CPallini wrote:

                        It's time to learn, then.

                        Keep in mind that the OP is doing embedded code and consequently what is actually available might be less than strict usage would otherwise suggest.

                        1 Reply Last reply
                        0
                        • A arnold_w

                          I am working with an embedded microcontroller (ARM) and I'm building with GCC. The following is fully possible for me to:

                          struct testStruct_s {
                          int dummy;
                          const char* string;
                          };

                          struct testStruct_s testStructArray[] = {
                          {0, "Hello World"},
                          {0, "Hello World Again"}
                          };

                          But why isn't the following possble?

                          struct testStruct_s {
                          int dummy;
                          int* array;
                          };

                          struct testStruct_s testStructArray[] = {
                          {0, {0, 1, 2, 3}},
                          {0, {0, 1, 2, 3, 4}}
                          };

                          Is there a workaround to achieve this? I do not want to specify the array values outside the struct so the following is not what I want:

                          int array1[] = {0, 1, 2, 3};
                          int array2[] = {0, 1, 2, 3, 4};

                          struct testStruct_s testStructArray[] = {
                          {0, array1},
                          {0, array2}
                          };

                          J Offline
                          J Offline
                          jschell
                          wrote on last edited by
                          #12

                          arnold_w wrote:

                          an embedded microcontroller (ARM)

                          Because of that I am going to presume that maybe you can't rely on the newest features (other suggestions). Didn't see anyone mention the old school approach which should work on any C compiler unless perhaps one goes back to the 70s (perhaps even then.) I am not going to try to even create pseudo code for this (way too long for me) but basic outline - Add attributes for the size of each array - All attributes EXCEPT arrays must be before arrays themselves. So arrays are at the end. - Alloc the struct based on the size of the array PLUS the appropriate sizes of the arrays. - Create helper methods that use and OFFSET to access the array pointer based on the sizes (attribute above) for each array. Google for the following for examples. Look for examples that have something like "int[] array" at the end of the structure.

                          C programming language struct dynamic array

                          One gotcha which is probably still relevant is that, maybe, C compilers attempt to 'align' attributes in the struct, these days. That means it might add filler that you are unaware of. If so there should be a compiler option, to remove that. This solution means that you cannot treat the array attributes as pointers. Specifically do not try to set them to another pointer. That is because the array storage is in the struct allocated block itself. So you cannot free it. And assignment would mean you couldn't free the assigned block either.

                          A 1 Reply Last reply
                          0
                          • L Lost User

                            Then it is easy enough to make your code simpler:

                            struct testStruct_s {
                            int dummy;
                            int* array;
                            };

                            int array1[] = {0, 1, 2, 3};
                            int array2[] = {0, 1, 2, 3, 4};
                            struct testStruct_s testStructArray[] = {
                            {0, array1},
                            {0, array2}
                            };

                            A Offline
                            A Offline
                            arnold_w
                            wrote on last edited by
                            #13

                            I am basically writing a table (several hundred lines) with lots of information into source code (basically, my source code is the documentation for it) and it makes it so much easier to read if information is where it belongs and not somewhere else. That's why I don't want to use this approach.

                            L 1 Reply Last reply
                            0
                            • J jschell

                              arnold_w wrote:

                              an embedded microcontroller (ARM)

                              Because of that I am going to presume that maybe you can't rely on the newest features (other suggestions). Didn't see anyone mention the old school approach which should work on any C compiler unless perhaps one goes back to the 70s (perhaps even then.) I am not going to try to even create pseudo code for this (way too long for me) but basic outline - Add attributes for the size of each array - All attributes EXCEPT arrays must be before arrays themselves. So arrays are at the end. - Alloc the struct based on the size of the array PLUS the appropriate sizes of the arrays. - Create helper methods that use and OFFSET to access the array pointer based on the sizes (attribute above) for each array. Google for the following for examples. Look for examples that have something like "int[] array" at the end of the structure.

                              C programming language struct dynamic array

                              One gotcha which is probably still relevant is that, maybe, C compilers attempt to 'align' attributes in the struct, these days. That means it might add filler that you are unaware of. If so there should be a compiler option, to remove that. This solution means that you cannot treat the array attributes as pointers. Specifically do not try to set them to another pointer. That is because the array storage is in the struct allocated block itself. So you cannot free it. And assignment would mean you couldn't free the assigned block either.

                              A Offline
                              A Offline
                              arnold_w
                              wrote on last edited by
                              #14

                              It doesn't matter to me where the arrays are actually stored, I just want the data the array is initialized with to be placed where it belong inside structure array. Basically, my source code is kind of a look-up table in this case, so it's purely a visual thing for readability.

                              1 Reply Last reply
                              0
                              • A arnold_w

                                I am basically writing a table (several hundred lines) with lots of information into source code (basically, my source code is the documentation for it) and it makes it so much easier to read if information is where it belongs and not somewhere else. That's why I don't want to use this approach.

                                L Offline
                                L Offline
                                leon de boer
                                wrote on last edited by
                                #15

                                For the record on GCC you can control the C standard it uses via the flag -std=C99 or C++ standard -std=C++98 (yes C99 equivalent in C++ is 98) Your GCC compiler should be defaulted to at least C11 or C14, in C or C++ unless it's really old like GCC version 4.7.

                                In vino veritas

                                1 Reply Last reply
                                0
                                Reply
                                • Reply as topic
                                Log in to reply
                                • Oldest to Newest
                                • Newest to Oldest
                                • Most Votes


                                • Login

                                • Don't have an account? Register

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • World
                                • Users
                                • Groups