arraysc

Trying to Understand Array Initilization within Struct in C


I am trying to initialize an array which is declared in C struct.

The goal is to use an array and pass it as an argument to a function, which then copies each element of the passed array and assigns it to an array within a struct.

#include <stdio.h>


typedef struct {
    int v;
    int arrayInStruct[];
} TEST;

void ProblemCode1(){
    TEST test1; //Array Declared after struct declaration.
    int array[5] = {1,2,3,4,5};
    for(int i = 0; i < 5; i++){
        test1.arrayInStruct[i] = array[i];
        printf("%d", test1.arrayInStruct[i]);
    }
    return;
}

void ProblemCode2(int a[]){
    //Array Pass by Value and elements assigned to struct array.
    TEST test2;
    test2.arrayInStruct[5] = 0;
    for(int i = 0; i < 5; i++){
        test2.arrayInStruct[i] = a[i];
        printf("%d", test2.arrayInStruct[i]);
    }
    return;
}


void ProblemCode3(int a[]){
    //Array Pass by Value and elements assigned to struct array 
    //and struct array initilzation missing as compared to ProblemCode2.
    TEST test2;
    for(int i = 0; i < 5; i++){
        test2.arrayInStruct[i] = a[i];
        printf("%d", test2.arrayInStruct[i]);
    }
    return;
}

void WorkingCode1(){
    int array[5] = {1,2,3,4,5};
    TEST test1; //Array Created Before Declaration of Struct and not passed via function.
    for(int i = 0; i < 5; i++){
        test1.arrayInStruct[i] = array[i];
        printf("%d", test1.arrayInStruct[i]);
    }
    printf("\n");
    return;
}

void WorkingCode2(){
    int array1[5] = {1,2,3,4,5};
    int array2[5] = {0};
    for(int i = 0; i < 5; i++){
        array2[i] = array1[i];
        printf("%d", array2[i]);
    }
    printf("\n");
    return;
}

int main(){
    //int passbyValue[] = {1,2,3,4,5};
    //ProblemCode1();
    //ProblemCode2(passbyValue);
    //ProblemCode3(passbyValue);
    WorkingCode1();
    WorkingCode2();
    return 0;
}

Could someone please explain why certain functions work and others don't?


Solution

  • Your struct type contains a flexible array member, i.e. one where the last member is an array of unspecified length. The size of such a struct doesn't include that of the flexible array member.

    These members can only really be used if instances of the struct are allocated dynamically, by allocating enough space for the struct itself plus enough for a certain number of the array elements.

    Since you're declaring instances of this struct on the stack, there's no space for the flexible array member. That means that anytime you attempt to read or write an element of the array you're accessing memory outside the bounds of the declared struct. Doing so triggers undefined behavior in your code.

    Since you're always treating this array as though it has 5 members, the simplest fix would be to explicitly declare the array in the struct to be that size:

    typedef struct {
        int v;
        int arrayInStruct[5];
    } TEST;
    

    Alternately, if you want to keep the flexible array member, you'll need to dynamically allocate any instance of the struct you use, adding sufficient space for the flexible array member:

    void ProblemCode1(){
        TEST *test1 = malloc(sizeof(TEST) + 5 * sizeof test1->arrayInStruct[0]);
        int array[5] = {1,2,3,4,5};
        for(int i = 0; i < 5; i++){
            test1->arrayInStruct[i] = array[i];
            printf("%d", test1->arrayInStruct[i]);
        }
        free(test1);
        return;
    }