Thread overview
#define-like behavior
Mar 14, 2023
Jeremy
Mar 14, 2023
Mike Parker
Mar 14, 2023
Jeremy
Mar 15, 2023
bomat
Mar 15, 2023
Paul Backus
Mar 15, 2023
bomat
Mar 14, 2023
Paul Backus
March 14, 2023

Hi, in C and C++ you can use #define to substitute a value in place of an identifier while preprocessing. If you initialize a new string and don't change its value after that, will the compiler substitute the string identifier with its value, like #define in C, or will it make a string in memory and refer to that?

March 14, 2023

On Tuesday, 14 March 2023 at 05:47:35 UTC, Jeremy wrote:

>

Hi, in C and C++ you can use #define to substitute a value in place of an identifier while preprocessing. If you initialize a new string and don't change its value after that, will the compiler substitute the string identifier with its value, like #define in C, or will it make a string in memory and refer to that?

Manifest constants in D have a similar effect as #defined values, e.g.:

enum someVal = 10;

writeln(someVal);

Here, the effect is the same as if you'd written writeln(10). The difference is that with the preprocessor, it's a text replacement on the source before the compiler gets ahold of it, but in D the compiler handles the substitution internally.

The same is true for string literals:

enum str = "Hello";
writeln(str);

String literals get special treatment from the compiler in that they are "interned".

auto s1 = "What's up?";
auto s2 = "What's up?";

The literal "What's up?" should be stored in the binary only once, so both s1 and s2 will point to the same location. Substitute a manifest constant and the effect should be the same:

enum greeting = "What's up?";
auto s1 = greeting;
auto s2 = greeting;

Just be aware that there's a consequence for array literals:

enum vals = [1, 2, 3];

auto a1 = vals;
auto a2 = vals;

This allocates two dynamic arrays, not one. Everywhere you use vals it's just like using the literal directly, which usually means an allocation.

March 14, 2023

On Tuesday, 14 March 2023 at 05:47:35 UTC, Jeremy wrote:

>

Hi, in C and C++ you can use #define to substitute a value in place of an identifier while preprocessing. If you initialize a new string and don't change its value after that, will the compiler substitute the string identifier with its value, like #define in C, or will it make a string in memory and refer to that?

In D, you can get #define-like behavior by declaring the string as a manifest constant, like this:

enum myString = "hello";

For more tips on how to translate C preprocessor idioms to D, take a look at "The C Preprocessor vs D" in the "Articles" section of dlang.org.

March 14, 2023

On Tuesday, 14 March 2023 at 06:20:29 UTC, Mike Parker wrote:

>

On Tuesday, 14 March 2023 at 05:47:35 UTC, Jeremy wrote:

>

[...]

Manifest constants in D have a similar effect as #defined values, e.g.:

[...]

Thanks a lot!

March 15, 2023

Just out of curiosity:
Can you explain to me why this is called an enum although it's clearly not an enumeration?
Seems like a random abuse of a keyword...

March 15, 2023

On Wednesday, 15 March 2023 at 16:40:52 UTC, bomat wrote:

>

Just out of curiosity:
Can you explain to me why this is called an enum although it's clearly not an enumeration?
Seems like a random abuse of a keyword...

It's shorthand for defining an unnamed enum with a single member:

enum
{
    myString = "hello"
}

D lets you leave out the {} in this case, for convenience.

March 15, 2023

On Wednesday, 15 March 2023 at 19:27:19 UTC, Paul Backus wrote:

>

It's shorthand for defining an unnamed enum with a single member: ...

Ah, I see. Thanks!