milanHrabos
milanHrabos

Reputation: 1965

how to copy to array inside struct?

How to copy to flexible array inside struct in c?

    #include <stdio.h>
    #include <string.h>
    
    typedef struct
    {
        int val;
        char buf[];
    } foo;
    
    int main()
    {
        foo f;
        f.val = 4;
        // f.buf = "asd"; -> invalid use of flexible array member
        memcpy(f.buf, "asd\0", 4);
        printf("%s\n", f.buf);
    }

output:

    asd
    *** stack smashing detected ***: terminated
    Aborted (core dumped)

Also, if the struct was declared as:

    typedef struct
    {
        char buf[];
    } foo

vscode editor gives error:

    incomplete type is not allow

and gcc gives error:

    error: flexible array member in a struct with no named members
        6 |     char buf[];

Why is array in struct now allowed but pointer is? (char *buf).

Also, If a struct has a flexible array, what is its sizeof(struct containsFlexArray)? How can I dynamically resolve its array, when it has no dimension?

EDIT: if the above works in C++, because the incomplete array "decay" to pointer of known length (8 bytes in x64), why is this not also the case in c? If I peek to asm, I see the program does not allocate enough stack for the struct (it allocates only space for foo.val member, but not bur foo.buf member, in which case the program tries to use override the foo.val member (by using its address instead of foo.buf), which causes the stack smashing detected. But why is it implemented this wrong way? (So I want to know the rationale behind introducing flexible array as well)

Upvotes: 1

Views: 353

Answers (3)

Alan Beveridge
Alan Beveridge

Reputation: 21

You did not initialize the buf[] array when you declared an instance in main(). The compiler does not know how much memory to allocate. The stack smashing is a compiler feature that keeps your program from doing... bad things to you computer. Add a number to your array declaration in typedef struct. Like this: ` #include <stdio.h> #include <string.h>

typedef struct
{
    int val;
    char buf[5];
} foo;

int main()
{
    foo f;
    f.val = 4;
    // f.buf = "asd"; -> invalid use of flexible array member
    memcpy(f.buf, "asd\0", 4);
    printf("%s\n", f.buf);
}`

Upvotes: 1

user5550963
user5550963

Reputation:

lets use intel/amd architecture here where char => 1 byte int => 4 and long is 8 bytes long.

Struct alignment is an issue here. You see when you declare a struct in c, compiler looks at it as individual block. So if you have a struct like this:

struct a {
   long l;
   char c1;
   char c2;
}

compiler looks at the first type used, and allocates 8 bytes of memory for l, looks at c and determines that c1 is shorter than l and rather than figure out what c1's type is, it allocates 8 bytes of data for c1. It does the same for c2. So you end up with struct that is 24 bytes long and only 10 are used. Where if you use this:

struct b {
  char c1;
  long l;
  char c2;
}

this will allocate 1 byte for c1, 8 byte for l, and 8 bytes for c2. So you end up with 17 bytes and 10 used. Where as if you have this:

struct b {
  char c1;
  char c2;
  long l;
}

well it allocates 1 byte for c1, 1 byte for c2, and 8 bytes for l. In total 10 bytes but all 10 are used.

So what does it have to do with array? You see if you have:

struct aa {
   char a;
   long b[];
}

This will know to allocate at least one byte for b initially. Where when you do not have char a,

struct aa {
   long b[];
}

Compiler might not allocate any memory (allocate 0 bytes), because it simply does not know how much to allocate.

EDIT: Left my PC and in mean time other answer popped up. The other answer is very good!!! But I hope this helps you understand what is going on.

Upvotes: 1

Pat. ANDRIA
Pat. ANDRIA

Reputation: 2412

You may want to read information on flexible array member here.

It seems as, when using a flexible array in a struct there must be at least one other data member and the flexible array member must be last.

And also you may have an element of clarification concerning the usage of flexible array members in C here

Upvotes: 3

Related Questions