Thread overview
translate C struct char array into D
Jul 30, 2021
workman
Jul 30, 2021
Paul Backus
Jul 30, 2021
Tejas
Jul 30, 2021
H. S. Teoh
Jul 30, 2021
Tejas
Jul 30, 2021
Paul Backus
Jul 30, 2021
jfondren
Jul 30, 2021
russhy
Aug 02, 2021
workman
July 30, 2021

I get want to define this struct in D:

struct test1 {
    struct test1 *prev;
    struct test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char data[];
};
struct test1 {
    test1 *prev;
    test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char* data;
};

when I compare the size, test1.sizeof is 48 and sizeof(struct test1) from C is 40.

Anyone can explain what should I do with this ?

If I use test1 as member of other struct, the total size will not match.

July 30, 2021

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

I get want to define this struct in D:

struct test1 {
    struct test1 *prev;
    struct test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char data[];
};
struct test1 {
    test1 *prev;
    test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char* data;
};

when I compare the size, test1.sizeof is 48 and sizeof(struct test1) from C is 40.

Anyone can explain what should I do with this ?

If I use test1 as member of other struct, the total size will not match.

char data[] in the C struct is not a pointer, but actually a C99 flexible array member, and does not count towards the struct's sizeof.

D does not have flexible array members, but you can simulate one using a struct method:

struct test1 {
    // member variables...

    char* data() {
        return cast(char*) (&this + 1);
    }
}
July 30, 2021

On Friday, 30 July 2021 at 14:40:17 UTC, Paul Backus wrote:

>

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

[...]

char data[] in the C struct is not a pointer, but actually a C99 flexible array member, and does not count towards the struct's sizeof.

D does not have flexible array members, but you can simulate one using a struct method:

struct test1 {
    // member variables...

    char* data() {
        return cast(char*) (&this + 1);
    }
}

B-but the performance penalty of having an extra level of indirection? Absolutely unacceptable!!

July 30, 2021

On Friday, 30 July 2021 at 14:40:17 UTC, Paul Backus wrote:

>

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

[...]

char data[] in the C struct is not a pointer, but actually a C99 flexible array member, and does not count towards the struct's sizeof.

D does not have flexible array members, but you can simulate one using a struct method:

struct test1 {
    // member variables...

    char* data() {
        return cast(char*) (&this + 1);
    }
}

By the way how is this safe? And how exactly are we even assigning the data to a variable/reference in this case? Can you please show an example demonstrating this?

July 30, 2021
On Fri, Jul 30, 2021 at 03:41:32PM +0000, Tejas via Digitalmars-d-learn wrote:
> On Friday, 30 July 2021 at 14:40:17 UTC, Paul Backus wrote:
[...]
> > ```d
> > struct test1 {
> >     // member variables...
> > 
> >     char* data() {
> >         return cast(char*) (&this + 1);
> >     }
> > }
> > ```
> > 
> > [1]: http://port70.net/~nsz/c/c99/n1256.html#6.7.2.1p16
> 
> B-but the performance penalty of having an extra level of indirection? Absolutely unacceptable!!

Premature optimization.

Any optimizer worth its salt would be able to inline such a trivial function as .data above.  Check the output of LDC -O, for example. (Don't talk to me about dmd, if you care about performance you'd use LDC instead.)


T

-- 
This is a tpyo.
July 30, 2021

On Friday, 30 July 2021 at 15:51:12 UTC, Tejas wrote:

>

On Friday, 30 July 2021 at 14:40:17 UTC, Paul Backus wrote:

>

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

[...]

char data[] in the C struct is not a pointer, but actually a C99 flexible array member, and does not count towards the struct's sizeof.

D does not have flexible array members, but you can simulate one using a struct method:

struct test1 {
    // member variables...

    char* data() {
        return cast(char*) (&this + 1);
    }
}

By the way how is this safe? And how exactly are we even assigning the data to a variable/reference in this case? Can you please show an example demonstrating this?

In order to use a flexible array member, you have to allocate extra memory beyond the end of the struct, and it's entirely your responsibility to ensure that you do not go out-of-bounds when accessing that memory.

July 30, 2021

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

I get want to define this struct in D:

struct test1 {
    struct test1 *prev;
    struct test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char data[];
};

The easy way: put a slice there instead of a fake array and accept that data's contents will be allocated separately. Slices will be more convenient to deal with in the language anyway.

The C89 way: add a zero-length array and deal with its .ptr in appropriately sized allocations that you manage yourself (or get from a C API).

A third way: something with https://dlang.org/phobos/core_lifetime.html#.emplace

import core.memory : pureMalloc, pureFree;
import std.conv : to;

struct Pascal {
    ubyte len;
    char[0] data;

    static Pascal* alloc(string s) {
        const len = s.length.to!ubyte;
        auto res = cast(Pascal*) pureMalloc(Pascal.sizeof + len);
        res.len = len;
        res.data.ptr[0 .. len] = s[0 .. len];
        return res;
    }

    char[] toString()() {
        return data.ptr[0 .. len];
    }
}

unittest {
    auto s = Pascal.alloc("hello");
    scope (exit) pureFree(s);
    assert(s.toString == "hello");
    assert((*s).sizeof == ubyte.sizeof);
}
July 30, 2021

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

I get want to define this struct in D:

struct test1 {
    struct test1 *prev;
    struct test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char data[];
};
struct test1 {
    test1 *prev;
    test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char* data;
};

when I compare the size, test1.sizeof is 48 and sizeof(struct test1) from C is 40.

Anyone can explain what should I do with this ?

If I use test1 as member of other struct, the total size will not match.

struct test1 {
    test1 *prev;
    test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char[0] data;
}

data.ptr to access its pointer

August 02, 2021

On Friday, 30 July 2021 at 21:53:48 UTC, russhy wrote:

>

On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:

>

I get want to define this struct in D:

struct test1 {
    struct test1 *prev;
    struct test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char data[];
};
struct test1 {
    test1 *prev;
    test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char* data;
};

when I compare the size, test1.sizeof is 48 and sizeof(struct test1) from C is 40.

Anyone can explain what should I do with this ?

If I use test1 as member of other struct, the total size will not match.

struct test1 {
    test1 *prev;
    test1 *next;
    size_t v1;
    size_t v2;
    size_t v3;
    char[0] data;
}

data.ptr to access its pointer

Thanks for you all for the explain and tips, I will try avoid embed this struct into parent.