c++ Initializing a struct with an array as a member

后端 未结 4 1284
旧巷少年郎
旧巷少年郎 2020-12-24 13:28

Edited again because it originally wasn\'t clear that I\'m trying to initialize the arrays at compile time, not at run time...


I\'ve got the following reduced

相关标签:
4条回答
  • 2020-12-24 13:49

    c++ doesn't have the same flexible array member as last element as c99. You should use a std::vector if you don't know how many elements or you should specify how many if you do.

    EDIT: You have said in your edit that the array is a runtime constant, so specify the size and it should work fine. g++ has no problem with the following code:

    struct TestStruct { // note typedef is not needed */
        int length;
        int values[3]; // specified the size
    };
    
    TestStruct t = {3, {0, 1, 2}};
    
    int main() {
        // main implicitly returns 0 if none specified
    }
    

    EDIT: to address your comment, you could use templates like this:

    template <int N>
    struct TestStruct {
        int length;
        int values[N];
    };
    
    TestStruct<3> t3 = {3, {0, 1, 2}};
    TestStruct<2> t2 = {2, {0, 1}};
    
    int main() {}
    

    The only problem is that there is no easy way to put both t2 and t3 in a container (like a list/vector/stack/queue/etc because they have different sizes. If you want that, you should use std::vector. Also, if you are doing that, then it isn't necessary to store the size (it is associated with the type). So you could do this instead:

    template <int N>
    struct TestStruct {
        static const int length = N;
        int values[N];
    };
    
    TestStruct<3> t3 = {{0, 1, 2}};
    TestStruct<2> t2 = {{0, 1}};
    
    int main() {}
    

    But once again, you cannot put t2 and t3 in a "collection" together easily.

    EDIT: All in all, it sounds like you (unless you store more data than just some numbers and the size) don't need a struct at all, and can't just use a plain old vector.

    typedef std::vector<int> TestStruct;
    
    
    int t2_init[] = { 0, 1, 2 };
    TestStruct t3(t3_init, t3_init + 3);
    
    int t2_init[] = { 0, 1 };
    TestStruct t2(t2_init, t2_init + 2);
    
    int main() {}
    

    Which would allow you to have both t2 and t3 in a collection together. Unfortunately std::vector doesn't (yet) have array style initializer syntax, so i've used a shortcut. But it's simple enough to write a function to populate the vectors in a nice fashion.

    EDIT: OK, so you don't need a collection, but you need to pass it to a function, you can use templates for that to preserve type safety!

    template <int N>
    struct TestStruct {
        static const int length = N;
        int values[N];
    };
    
    TestStruct<3> t3 = {{0, 1, 2}};
    TestStruct<2> t2 = {{0, 1}};
    
    template <int N>
    void func(const TestStruct<N> &ts) { /* you could make it non-const if you need it to modify the ts */
        for(int i = 0; i < N; ++i) { /* we could also use ts.length instead of N here */
            std::cout << ts.values[i] << std::endl;
        }
    }
    
    // this will work too...
    template <class T>
    void func2(const T &ts) { 
        for(int i = 0; i < ts.length; ++i) {
            std::cout << ts.values[i] << std::endl;
        }
    }
    
    int main() {
        func(t2);
        func(t3);
        func2(t2);
    }
    
    0 讨论(0)
  • 2020-12-24 13:50

    GCC/Clang support the following extension

    
        typedef struct TestStruct
        {
            int length;
            int* values;
        };
    
        TestStruct t = {3, (int[]){0, 1, 2}};
        TestStruct t2 = {4, (int[]){0, 1, 2, 3}};
    
    
    0 讨论(0)
  • 2020-12-24 13:53
    struct TestStruct {
        int length;
        const int *values;
    };
    
    static const uint8_t TEST_STRUCT_VAL_1[] = {0, 1, 2};
    const TestStruct t1 = {3, TEST_STRUCT_VAL_1};
    
    static const uint8_t TEST_STRUCT_VAL_2[] = {0, 1, 2, 3};
    const TestStruct t2 = {4, TEST_STRUCT_VAL_2};`
    

    In my case, stm32 programming with gcc/g++, the value array is only raw data storage, so it is static const, and would be stored in flash. I use this way to store font patterns for lcd display.

    using template is typing saving, but not size saving.

    0 讨论(0)
  • 2020-12-24 13:55

    VLA is only supported in C99. C++ doesn't support that. From http://gcc.gnu.org/c99status.html, gcc supports VLA now.

    0 讨论(0)
提交回复
热议问题