Thread overview
Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
Dec 29, 2020
Arjan
Dec 29, 2020
Arjan
Dec 29, 2020
H. S. Teoh
Dec 29, 2020
H. S. Teoh
Dec 29, 2020
Arjan
December 29, 2020
see https://en.cppreference.com/w/c/language/struct

It seems the 'static' must NOT be used here to get the equivalent behavior of c, when left in the assertions will fail.

Is this expected?

```
unittest
{

struct W
{
align(1):
    long k;
    long l;
}

struct V
{
align(1):
    union // anonymous union
    {
        /*static*/ struct // anonymous structure
        {
            long i;
            long j;
        }
        W w;
   }
   int m;
}

V v1;

v1.i = 2;
assert( 2 == v1.w.k );
v1.w.l = 5;
assert( 5 == v1.j );
}
```




December 29, 2020
On 12/29/20 7:38 AM, Arjan wrote:
> see https://en.cppreference.com/w/c/language/struct
> 
> It seems the 'static' must NOT be used here to get the equivalent behavior of c, when left in the assertions will fail.
> 
> Is this expected?
> 
> ```
> unittest
> {
> 
> struct W
> {
> align(1):
>      long k;
>      long l;
> }
> 
> struct V
> {
> align(1):
>      union // anonymous union
>      {
>          /*static*/ struct // anonymous structure
>          {
>              long i;
>              long j;
>          }
>          W w;
>     }
>     int m;
> }
> 
> V v1;
> 
> v1.i = 2;
> assert( 2 == v1.w.k );
> v1.w.l = 5;
> assert( 5 == v1.j );
> }
> ```

I added in some printouts of the addresses of the variables.

It appears that if you add static to the struct, it now becomes a static member of the union, which means it's not an instance variable, and is now a thread-local variable. Its address doesn't even coincide remotely with the address of v1.

What is the equivalent behavior for C that you are expecting? The usage of "static struct" doesn't appear in that page you linked to.

-Steve
December 29, 2020
On Tuesday, 29 December 2020 at 14:42:07 UTC, Steven Schveighoffer wrote:
> On 12/29/20 7:38 AM, Arjan wrote:
>> see https://en.cppreference.com/w/c/language/struct
>> 
> I added in some printouts of the addresses of the variables.
>
> It appears that if you add static to the struct, it now becomes a static member of the union, which means it's not an instance variable, and is now a thread-local variable. Its address doesn't even coincide remotely with the address of v1.
>
> What is the equivalent behavior for C that you are expecting? The usage of "static struct" doesn't appear in that page you linked to.

On the C/C++ side there is no static. I added those on the D side to to make sure there is no context pointer being added, since that will change the layout and size of struct. (in the c/c++ code those unions and structs are nested several levels deep)

Based on this: https://dlang.org/spec/struct.html#nested
I expected to have the equivalent of C behavior in D by using the static keyword, which in this case just caused havoc. So the other way around.

December 29, 2020
On Tue, Dec 29, 2020 at 05:13:19PM +0000, Arjan via Digitalmars-d-learn wrote: [...]
> On the C/C++ side there is no static. I added those on the D side to to make sure there is no context pointer being added, since that will change the layout and size of struct. (in the c/c++ code those unions and structs are nested several levels deep)

You need to add 'static' to the (outer) struct declarations in your unittest block, because otherwise they *will* have a context pointer. This is because unittest blocks are compiled as if they were functions, and struct declarations in a function do acquire context pointers.


--T
December 29, 2020
On 12/29/20 12:13 PM, Arjan wrote:
> On Tuesday, 29 December 2020 at 14:42:07 UTC, Steven Schveighoffer wrote:
>> On 12/29/20 7:38 AM, Arjan wrote:
>>> see https://en.cppreference.com/w/c/language/struct
>>>
>> I added in some printouts of the addresses of the variables.
>>
>> It appears that if you add static to the struct, it now becomes a static member of the union, which means it's not an instance variable, and is now a thread-local variable. Its address doesn't even coincide remotely with the address of v1.
>>
>> What is the equivalent behavior for C that you are expecting? The usage of "static struct" doesn't appear in that page you linked to.
> 
> On the C/C++ side there is no static. I added those on the D side to to make sure there is no context pointer being added, since that will change the layout and size of struct. (in the c/c++ code those unions and structs are nested several levels deep)
> 
> Based on this: https://dlang.org/spec/struct.html#nested
> I expected to have the equivalent of C behavior in D by using the static keyword, which in this case just caused havoc. So the other way around.
> 

structs only add context pointers if nested in functions (and even then, only if it's not POD). If nested in structs, classes, or unions (or anything else), then no context pointer is added.

So the answer is, don't use static.

-Steve
December 29, 2020
On 12/29/20 12:45 PM, H. S. Teoh wrote:
> On Tue, Dec 29, 2020 at 05:13:19PM +0000, Arjan via Digitalmars-d-learn wrote:
> [...]
>> On the C/C++ side there is no static. I added those on the D side to
>> to make sure there is no context pointer being added, since that will
>> change the layout and size of struct. (in the c/c++ code those unions
>> and structs are nested several levels deep)
> 
> You need to add 'static' to the (outer) struct declarations in your
> unittest block, because otherwise they *will* have a context pointer.

Not if the struct is POD. And in this case, they are all POD (no methods).

-Steve
December 29, 2020
On Tuesday, 29 December 2020 at 17:49:20 UTC, Steven Schveighoffer wrote:
> On 12/29/20 12:13 PM, Arjan wrote:
>> On Tuesday, 29 December 2020 at 14:42:07 UTC, Steven Schveighoffer wrote:
>>> On 12/29/20 7:38 AM, Arjan wrote:
>>>> see https://en.cppreference.com/w/c/language/struct

> structs only add context pointers if nested in functions (and even then, only if it's not POD). If nested in structs, classes, or unions (or anything else), then no context pointer is added.
>
> So the answer is, don't use static.

That is what I discovered indeed. Thanks both for answering and the additional information. This could however be made more explicit and clear in the documentation.

December 29, 2020
On Tue, Dec 29, 2020 at 12:50:06PM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote:
> On 12/29/20 12:45 PM, H. S. Teoh wrote:
[...]
> > You need to add 'static' to the (outer) struct declarations in your unittest block, because otherwise they *will* have a context pointer.
> 
> Not if the struct is POD. And in this case, they are all POD (no
> methods).
[...]

Hmm, I didn't know that!  I thought they always get a context pointer. Maybe I got confused with nested functions.  I stand corrected.


--T