How would the equivalent C type be in D?

FeepingCreature feepingcreature at gmail.com
Wed Mar 1 08:26:07 UTC 2023


On Wednesday, 1 March 2023 at 08:12:05 UTC, rempas wrote:
> I'm looking into 
> [this](https://www.x.org/releases/X11R7.7/doc/libxcb/tutorial/index.html) tutorial to learn XCB and I'm trying to write the code in D with betterC. In the section 9.1 (sorry, I cannot give a section link, the article does not give us this ability), I'm facing a problem and my program exits with the exit code: "-11". I suspect that this happens because I haven't translated the following code the right way:
>
> ```d
> uint32_t value[1];
> value[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> I originally tried to translate this as:
>
> ```d
> uint[1] value;
> value[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> But then, when I tried to compile the program, I got the 
> following error:
>
> ```
> Error: function `headers.xcb_create_gc(xcb_connection_t* c, 
> uint cid, uint drawable, uint value_mask, const(void)* 
> value_list)` is not callable using argument types 
> `(xcb_connection_t*, uint, uint, uint, uint[1])`
> src/draw.d(18,16):        cannot pass argument `value` of type 
> `uint[1]` to parameter `const(void)* value_list`
> ```
>
> So I thought of doing the following:
>
> ```d
> uint* value;
> value[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> Now the program complies but I get the "-11" exit code. Another 
> thing I thought (which is probably the same thing under the 
> hood but done a different way):
>
> ```d
> const(void)* value;
> (cast(ubyte*)value)[0] = screen.black_pixel;
> xcb_create_gc(connection, black, win, mask, value);
> ```
>
> Same results. Any ideas?

11 is SIGSEGV. A segfault, or access violation, happens when you 
try to access unallocated memory. In this case, let me annotate 
your code so it's easier to see what's happening:

```d
// null is the default value for a pointer
uint* value = null;
// because `value` is null, the first index also lies at null.
assert(&value[0] is null);
// So we try to store screen.black_pixel at memory address null, 
which is unallocated.
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value);
```

As there is no memory segment allocated at address null, the CPU 
indicates a segmentation fault, which terminates the program.

So yes, `xcb_create_gc` wants a `uint*` parameter, but not just 
any `uint*` will do: it has to point to valid memory. Going back 
to the first snippet, what's happening here is that in C, arrays 
implicitly convert to pointers, because C doesn't have a notion 
of array types as distinct from pointer types. So you can have a 
variable declared as `uint[1]`, but pass it to a parameter that 
expects `uint*`, and the value that is passed will just be the 
address of the first field of the array. However, even in C, if 
you try to define `value` as `uint*`, it will segfault in the 
same way. Instead, in D, you need to tell the compiler to define 
an array of size 1, and then pass a pointer to the array's first 
member explicitly:

```d
uint32_t[1] value;
value[0] = screen.black_pixel;
// this is what C does under the hood
xcb_create_gc(connection, black, win, mask, &value[0]);
```

Or shorter, but with the same effect:

```d
uint32_t[1] value;
value[0] = screen.black_pixel;
xcb_create_gc(connection, black, win, mask, value.ptr);
```



More information about the Digitalmars-d-learn mailing list