digitalmars.D.learn - How would the equivalent C type be in D?
- rempas (38/38) Mar 01 2023 I'm looking into
- FeepingCreature (40/78) Mar 01 2023 11 is SIGSEGV. A segfault, or access violation, happens when you
- FeepingCreature (18/23) Mar 01 2023 To expand on this:
- rempas (10/50) Mar 01 2023 Thank you! You are amazing for explaining it! I was so focused on
- FeepingCreature (21/30) Mar 07 2023 Yay!
- rempas (2/5) Mar 07 2023 Thank you for the info!
- FeepingCreature (22/31) Mar 07 2023 Yay!
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?
Mar 01 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); ```
Mar 01 2023
On Wednesday, 1 March 2023 at 08:26:07 UTC, FeepingCreature wrote:```d uint32_t[1] value; value[0] = screen.black_pixel; xcb_create_gc(connection, black, win, mask, value.ptr); ```To expand on this: ```d uint32_t[2] value; uint32_t* value_ptr = value.ptr; // We are allowed to access the pointer at index 0 // because we declared the value it points to, to be size 2. value_ptr[0] = 0; // This is also allowed, because `value_ptr` is // a pointer to two sequential `uint32_t` in memory. value_ptr[1] = 0; // But this access would segfault, because it's trying to write // to the third element of a two-element array: value_ptr[2] = 0; ``` Note: I just lied; `value_ptr[2]` would not segfault, for somewhat technical reasons; but it *would* corrupt your program's memory. At any rate, it's an invalid operation.
Mar 01 2023
On Wednesday, 1 March 2023 at 08:26:07 UTC, FeepingCreature wrote: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); ```Thank you! You are amazing for explaining it! I was so focused on thinking that I'm doing something wrong with the type that I didn't noticed that the pointers, points to nowhere so the function obviously has nowhere to write to. Like... OMG! And I want to make a fully fledged compiler when making stupid mistakes like that. Btw, When I executed the program, I got "Error Program exited with code -11". You said that the code was "11". What about that dash? If it is not a "minus" and it's just the dash symbol, then what's the idea?
Mar 01 2023
On Wednesday, 1 March 2023 at 09:37:48 UTC, rempas wrote:Thank you! You are amazing for explaining it! I was so focused on thinking that I'm doing something wrong with the type that I didn't noticed that the pointers, points to nowhere so the function obviously has nowhere to write to. Like... OMG! And I want to make a fully fledged compiler when making stupid mistakes like that. Btw, When I executed the program, I got "Error Program exited with code -11". You said that the code was "11". What about that dash? If it is not a "minus" and it's just the dash symbol, then what's the idea?Yay! Yes, that is a bit weird. First of all, the actual signal is 11 ``` $ grep SIGSEGV /usr/include/bits -R /usr/include/bits/signum-generic.h:#define SIGSEGV 11 /* Invalid access to storage. */ ``` As per the POSIX spec https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap0 .html#tag_18_21_18. signal exits must be reported with exit codes above 128. Customarily, shells will simply add 128 to the signal: ``` $ cat test.c; gcc test.c -otestc; ./testc; echo $? int main() { int* ip = 0; *ip = *ip; return 0; } Segmentation fault 139 ``` 139 being 128 + 11, but POSIX does not specify *how* the signal code is converted to an exit code. For instance, Python reports a signal 11 exit as -11. Strictly speaking, -11 is "above 128" in two's complement, corresponding to unsigned 245. But I don't know why Python does this. Presumably your shell does it the same way?
Mar 07 2023
On Tuesday, 7 March 2023 at 09:05:45 UTC, FeepingCreature wrote:Yay! Yes, that is a bit weird. First of all, the actual signal is 11 [...]Thank you for the info!
Mar 07 2023
On Wednesday, 1 March 2023 at 09:37:48 UTC, rempas wrote:Thank you! You are amazing for explaining it! I was so focused on thinking that I'm doing something wrong with the type that I didn't noticed that the pointers, points to nowhere so the function obviously has nowhere to write to. Like... OMG! And I want to make a fully fledged compiler when making stupid mistakes like that. Btw, When I executed the program, I got "Error Program exited with code -11". You said that the code was "11". What about that dash? If it is not a "minus" and it's just the dash symbol, then what's the idea?Yay! (Definitely make a compiler, it's a great way to learn.) Yes, that is a bit weird. First of all, the actual signal is 11 ``` $ grep SIGSEGV /usr/include/bits -R /usr/include/bits/signum-generic.h:#define SIGSEGV 11 /* Invalid access to storage. */ ``` As per the POSIX spec https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap0 .html#tag_18_21_18. signal exits must be reported with exit codes above 128. Customarily, shells will simply add 128 to the signal: ``` $ cat test.c; gcc test.c -otestc; ./testc; echo $? int main() { int* ip = 0; *ip = *ip; return 0; } Segmentation fault 139 ``` 139 being 128 + 11, but POSIX does not specify *how* the signal code is converted to an exit code. For instance, Python reports a signal 11 exit as -11. Strictly speaking, -11 is "above 128" in two's complement, corresponding to unsigned 245. But I don't know why Python does this. Presumably your shell does it the same way?
Mar 07 2023