www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Nasty supprise when using c 'anonymous struct and union' in D with

reply Arjan <arjan ask.me.to> writes:
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 );
}
```
Dec 29 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
Dec 29 2020
parent reply Arjan <arjan ask.me.to> writes:
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.
Dec 29 2020
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Dec 29 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
Dec 29 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Dec 29 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
Dec 29 2020
parent Arjan <arjan ask.me.to> writes:
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.
Dec 29 2020