August 23, 2022

On Friday, 19 August 2022 at 13:42:58 UTC, Hipreme wrote:

>

[...]

What’s great is that structs defined in C imported in D and structs defined in D imported in D will have completely different initial values despite being syntactically identical!

// foo_c.c
struct Foo {
    float x;
};

// foo_d.d
struct Foo {
    float x;
};

// main.d
import foo_d;
import foo_c;
import std.stdio: writeln;

void main(){
    foo_d.Foo f_d;
    foo_c.Foo f_c;
    writeln(f_d); // Foo(nan)
    writeln(f_c); // Foo(0)
}
August 23, 2022
On 8/23/22 13:44, Dave P. wrote:
> On Friday, 19 August 2022 at 13:42:58 UTC, Hipreme wrote:
>> [...]

> will have completely different initial values

Although C does not initialize variables, sometimes both C and D floats can have the same exact bit pattern.

> despite being syntactically identical!

C and D are different languages.

>      writeln(f_d); // Foo(nan)

That will always be the case.

>      writeln(f_c); // Foo(0)

And yes, 0 happens to be a valid garbage value.

Ali

August 23, 2022

On 8/23/22 5:24 PM, Ali Çehreli wrote:

>

Although C does not initialize variables, sometimes both C and D floats can have the same exact bit pattern.

I'm wondering if D does not zero-initialize structs that are from importC?

-Steve

August 23, 2022
On Tuesday, 23 August 2022 at 21:24:10 UTC, Ali Çehreli wrote:
> On 8/23/22 13:44, Dave P. wrote:
> > On Friday, 19 August 2022 at 13:42:58 UTC, Hipreme wrote:
> >> [...]
>
> > will have completely different initial values
>
> Although C does not initialize variables, sometimes both C and D floats can have the same exact bit pattern.
>
> > despite being syntactically identical!
>
> C and D are different languages.
>

This is a struct defined in C being used in D via ImportC.

> >      writeln(f_d); // Foo(nan)
>
> That will always be the case.
>
> >      writeln(f_c); // Foo(0)
>
> And yes, 0 happens to be a valid garbage value.

The default value for a struct imported via importC is all bits 0. This is not a “garbage value”.


August 23, 2022
On 8/23/22 14:40, Dave P. wrote:

>> And yes, 0 happens to be a valid garbage value.
>
> The default value for a struct imported via importC is all bits 0.

Steve said the same thing but I don't see it on the ImportC page (yet?):

  https://dlang.org/spec/importc.html

I wonder why D would do that.

> This is not a “garbage value”.

D could set all bits to any other value and it would still be fine because either C's initialization function would be called on the object (some programmers call memset), or the programmer did not care.

Ali

August 23, 2022
On 8/23/2022 1:44 PM, Dave P. wrote:
> What’s great is that structs defined in C imported in D and structs defined in D imported in D will have completely different initial values despite being syntactically identical!

Let's have some fun with the following C program:

-----------
 #include <stdio.h>

 struct Foo { float x; };

 int main()
 {
    struct Foo f;
    printf("%g\n", f.x);
 }

 gcc test.c
 ./a.out
 2.12133e-15
-------------

Oh well!
August 23, 2022
On Tuesday, 23 August 2022 at 21:53:35 UTC, Ali Çehreli wrote:
> On 8/23/22 14:40, Dave P. wrote:
>
> >> And yes, 0 happens to be a valid garbage value.
> >
> > The default value for a struct imported via importC is all
> bits 0.
>
> Steve said the same thing but I don't see it on the ImportC page (yet?):
>
>   https://dlang.org/spec/importc.html
>
> I wonder why D would do that.

Global and static variables in C are initialized to all-zero bits, regardless of type. Here's the relevant paragraph from the C11 standard:

> If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:
> 
>     if it has pointer type, it is initialized to a null pointer;
>     if it has arithmetic type, it is initialized to (positive or unsigned) zero;
>     if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
>     if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

Source: http://port70.net/~nsz/c/c11/n1570.html#6.7.9p10

Presumably this behavior was implemented in an attempt to conform to this part of the C standard.
August 23, 2022

On 8/23/22 6:33 PM, Walter Bright wrote:

>

On 8/23/2022 1:44 PM, Dave P. wrote:

>

What’s great is that structs defined in C imported in D and structs defined in D imported in D will have completely different initial values despite being syntactically identical!

Let's have some fun with the following C program:


 #include <stdio.h>

 struct Foo { float x; };

 int main()
 {
    struct Foo f;
    printf("%g\n", f.x);
 }

 gcc test.c
 ./a.out
 2.12133e-15

Oh well!

Since you are looking at it, the original code is not a C function, it's a D function using a struct defined using C (imported via ImportC).

What happens in that case?

On one hand, it's a C struct. But on the other hand, it's a D function. Who's rules are used?

-Steve

August 23, 2022
On 8/23/2022 5:00 PM, Steven Schveighoffer wrote:
> On one hand, it's a C struct. But on the other hand, it's a D function. Who's rules are used?

The C rules. This is because D is importing C code, so it better behave like C code. C code does initialize floats and doubles to 0.0 if they are placed in static data. It is not reasonable that D would leave imported C structures uninitialized when C does, and so initializing them to 0.0 is a reasonable choice.

August 23, 2022
On 8/23/2022 4:35 PM, Paul Backus wrote:
> Presumably this behavior was implemented in an attempt to conform to this part of the C standard.

Yes. It's not a bug.