-4

Please give me the answer. Thanks

    struct ZMessage {
    uint8_t id[sizeof(struct ZID)];
    struct ZBlock block[1]; //what different 'ZBlock block'
};
Edward
  • 1
  • 1

1 Answers1

2

C and C++ are different languages. struct ZBlock block[1]; is a C syntax.

In classic C a name of struct is ... not a type. It's a name of block (of variables). C got concept of anonymous struct. Anonymous structs allowed to create separate block of variables or fields with proper alignment, i.e following Test would have field b started from a new word, i.e. size of block will be 4 if size of short is 2.

// this is correct ONLY in C
int main(void)
{
    struct Test {
      short a : 5;
      struct {
      short b : 5;
      short c : 6;
      };
    };
    
    // you can have a name of variable matching a name of block.
    // regardless of name, declaration without struct is forbidden
    struct Test Test; 

    Test.b = 3;
    printf("Test.b equals to %d, size of test %d", Test.b, sizeof(Test)); 
    // Output: Test.b equals to 3, size of test 4
    return EXIT_SUCCESS;
}

Therefore in any context where you declare a variable or function parameter you have to precede struct-id by keyword struct to create a type-id.

In C++ struct is a class-type. It's name can be used as type-id, so you don't need a keyword struct. C++ doesn't allow anonymous structs but allows anonymous unions and anonymous namespace.

In fact that you declare ZMessage without a typedef suggest that it is C++ context or a recent C version. C syntax is supported for backward compatibility of header files.

About array of size 1. In that case expression consisting out of name block is a pointer to array of ZBlock. Using size 1 to declare a flexible array according to C standard is no longer correct. C had a special rule that you can use pointer arithmetics (and operator[] as extent of that) to access implicitly allocated memory after this struct, if array is the last member of struct and got incomplete type.

In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply

Creation of such might look like this:

// might have size 4 or size 8 - greater than sizeof(short)
struct Test {
  short size;
  short data[]; // Incomplete array type - C11. 
  // `short data[1]; is NO longer a flexible array.
};

int count =  10;
// note: C doesn't support Test::data construct
// C++ would require a type cast (Test*)
struct Test* pack = malloc(sizeof(struct Test) + count*sizeof(short)); 
pack->size = count;
pack->data[0] = 4;
pack->data[1] = 8;
...

Here is a problem with padding. We most likely allocate more memory than we need. correct way is to determine offset of address beyond last element of data[]. In C, while sizeof(Test) can be, e.g. 8, offset of data[0] can be still 2.

 // such usage of offsetof is undefined in C++
 struct Test* pack = malloc(offsetof(struct Test, data[count])); 

C++ explicitly doesn't allow to go beyond boundary of object, i.e. beyond boundary of struct. But some compilers support it as extension, usually with no array size declared in that case or with size 1 in case of some compilers. Caveat with those is that it's not consistent if compiler assumes struct to include first member of single array or array can have a zero length.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • ```struct ZBlock block[1]``` is not special usage in C? – Edward May 25 '22 at 09:45
  • @Bob__ hmm, they completely failed to voice that – Swift - Friday Pie May 25 '22 at 09:53
  • @Bob_ yes, I have a problem with an array of one element. – Edward May 25 '22 at 10:04
  • @Edward Eh, in old C it could be flexible array. With some C++ compilers it is their way to declare flexible array. Current C syntax. Please add expression of your concern to question. – Swift - Friday Pie May 25 '22 at 10:21
  • 1
    @Edward array with size 1 is usually used for flexible array member in unsupported C compilers, or in C++: [What is the correct way of interop'ing with C flexible array members from C++?](https://stackoverflow.com/q/43839009/995714), [Why do some structures end with an array of size 1?](https://devblogs.microsoft.com/oldnewthing/?p=38043), [bmiColors field of BITMAPINFO structure](https://stackoverflow.com/a/58618191/995714), [Are flexible array members valid in C++?](https://stackoverflow.com/q/4412749/995714) – phuclv May 25 '22 at 10:53