www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - constant pointer failing to compile

reply Josh Holtrop <jholtrop gmail.com> writes:
I am trying to port a small C project to D and am getting a 
compilation error I don't understand.

I've simplified the situation down to the example here.

This C version compiles fine:

```c
#include <stdio.h>

static const unsigned char data[] = {1, 2, 3, 4};

static const unsigned char * p = &data[0];

int main(int argc, char * argv[])
{
     printf("*p = %u\n", *p);
     return 0;
}
```

My attempt to do the same in D:

```d
import std.stdio;

__gshared immutable ubyte[] data = [1, 2, 3, 4];

__gshared immutable ubyte * p = data.ptr;

int main()
{
     writeln("*p = ", *p);
     return 0;
}
```

This fails to compile with gdc:

```
constarrptr.d:5:45: error: cannot use non-constant CTFE pointer 
in an initializer ‘&[cast(ubyte)1u, cast(ubyte)2u, cast(ubyte)3u, 
cast(ubyte)4u][0]’
     5 | __gshared immutable(immutable(ubyte) *) p = data.ptr;
       |                                             ^
```

And also with ldc2:

```
constarrptr.d(5): Error: cannot use non-constant CTFE pointer in 
an initializer `cast(immutable(ubyte)*)data`
```

Why? And how can I do the equivalent to what I have been doing in 
C? I want these pointers to be generated at compile time, not 
initialized at runtime.

(the full project is generating this file containing the data 
array (which is much longer) and multiple pointer constants to 
locations within it)
Apr 05 2023
next sibling parent reply Mathias LANG <geod24 gmail.com> writes:
 immutable ubyte[4] data = [1, 2, 3, 4];
Using a static array instead of a slice will do the trick. You can leave the `__gshared` if you want, but it is redundant on a global, initialized `immutable` variable.
Apr 05 2023
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/5/23 8:59 PM, Mathias LANG wrote:
 immutable ubyte[4] data = [1, 2, 3, 4];
Using a static array instead of a slice will do the trick. You can leave the `__gshared` if you want, but it is redundant on a global, initialized `immutable` variable.
I found out the same thing. But I don't really understand why. the error message gives a slight clue: ``` cannot use non-constant CTFE pointer in an initializer ‘&[cast(ubyte)1u, cast(ubyte)2u, cast(ubyte)3u, cast(ubyte)4u][0]’ ``` That *isn't* a CTFE pointer, it's a pointer to a static immutable. Yes, the initialization value is a CTFE array, but the variable itself has an address. Notice how the expression has turned into an address of the initializer. I think this is a compiler bug. -Steve
Apr 05 2023
prev sibling parent Josh Holtrop <jholtrop gmail.com> writes:
On Thursday, 6 April 2023 at 00:59:12 UTC, Mathias LANG wrote:
 immutable ubyte[4] data = [1, 2, 3, 4];
Using a static array instead of a slice will do the trick. You can leave the `__gshared` if you want, but it is redundant on a global, initialized `immutable` variable.
Yes, thank you, using static arrays did work. And thanks for the note on __gshared as well.
Apr 06 2023
prev sibling next sibling parent Salih Dincer <salihdb hotmail.com> writes:
On Thursday, 6 April 2023 at 00:46:26 UTC, Josh Holtrop wrote:
 ```
 constarrptr.d(5): Error: cannot use non-constant CTFE pointer 
 in an initializer `cast(immutable(ubyte)*)data`
 ```

 Why? And how can I do the equivalent to what I have been doing 
 in C? I want these pointers to be generated at compile time, 
 not initialized at runtime.

 (the full project is generating this file containing the data 
 array (which is much longer) and multiple pointer constants to 
 locations within it)
You have 2 options: First, to use .ptr, or second, to do the initialization in static this: ```d import std.stdio; static const char[] d; static const char * p; static this() { d = [97, 98, 99]; p = &d[0]; // == d.ptr; } void main() { printf("%.*s\n", cast(int)d.length, d.ptr); writeln("*p = ", *p); }/* Prints: abc *p = a */ ``` SDB 79
Apr 06 2023
prev sibling parent reply Jacob Shtokolov <jacob.100205 gmail.com> writes:
On Thursday, 6 April 2023 at 00:46:26 UTC, Josh Holtrop wrote:
 I am trying to port a small C project to D and am getting a 
 compilation error I don't understand.
It seems like the compiler is just missing some type hints. Try this: ```d import std.stdio; __gshared immutable ubyte[4] data = [1, 2, 3, 4]; __gshared immutable ubyte* p = data.ptr; int main() { writeln("*p = ", *p); return 0; } ``` Look how I provided the `ubyte[4]` hint to the compiler so it thinks that it's a constant. I'm not sure why this happens, but sometimes the compiler can't deduce static arrays, especially if you're explicitly saying that they're not static (`ubyte[]`).
Apr 06 2023
parent Jacob Shtokolov <jacob.100205 gmail.com> writes:
On Thursday, 6 April 2023 at 20:23:29 UTC, Jacob Shtokolov wrote:
 On Thursday, 6 April 2023 at 00:46:26 UTC, Josh Holtrop wrote:
 I am trying to port a small C project to D and am getting a
Ah, just noticed that other people have already responded! Sorry about that! BTW, your `&data[0]` C-like pointer will also work in D's version, although it's probably a bit uglier.
Apr 06 2023