www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - translate C struct char array into D

reply workman <workman gmail.com> writes:
I get want to define this struct in D:

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

```d
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.
Jul 30 2021
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:
 I get want to define this struct in D:

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

 ```d
 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][1], 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: ```d struct test1 { // member variables... char* data() { return cast(char*) (&this + 1); } } ```
Jul 30 2021
next sibling parent reply Tejas <notrealemail gmail.com> writes:
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][1], 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: ```d 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!!
Jul 30 2021
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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);
     }
 }
 ```
 

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.
Jul 30 2021
prev sibling parent reply Tejas <notrealemail gmail.com> writes:
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][1], 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: ```d 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?
Jul 30 2021
parent Paul Backus <snarwin gmail.com> writes:
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][1], 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: ```d 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.
Jul 30 2021
prev sibling next sibling parent jfondren <julian.fondren gmail.com> writes:
On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:
 I get want to define this struct in D:

 ```c
 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 ```d 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); } ```
Jul 30 2021
prev sibling parent reply russhy <russhy gmail.com> writes:
On Friday, 30 July 2021 at 14:05:58 UTC, workman wrote:
 I get want to define this struct in D:

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

 ```d
 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.
```d struct test1 { test1 *prev; test1 *next; size_t v1; size_t v2; size_t v3; char[0] data; } ``` data.ptr to access its pointer
Jul 30 2021
parent workman <workman gmail.com> writes:
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:

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

 ```d
 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.
```d 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.
Aug 02 2021