LoginSignup
4
0

More than 1 year has passed since last update.

はじめに

昨年のアドベントカレンダーにあったGoクイズが正直うらやましく思い、D言語クイズを考えてみました。

D言語を知らない方でも、ソースコードは何となく読める程度の内容なので、これを機会にD言語に興味を持っていただけると幸いです。

クイズの前提

Online D Editor(2021/12/14現在)での実行結果をクイズの正解とさせていただきます。

Online D Editorの環境情報(2021/12/14現在)

import std;
void main()
{
    writeln(__VENDOR__);
    writeln(__VERSION__);
    version(BigEndian)
    {
        writeln("Big endian byte order ");
    }
    else version(LittleEndian)
    {
        writeln("Little endian byte order");
    }
}
実行結果
Digital Mars D
2098
Little endian byte order

ここから問題です。

問題1

ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

import std;
void func1()
{
    scope(exit) write("1");
    write("2");
    throw new Exception("");
}
void main()
{
    scope(exit) write("3");
    scope(exit) write("4");
    write("5");
    try
    {
        func1();
    }
    catch (Exception e)
    {
    }
    write("6");
}

問題2

ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

import std;
void main()
{
    ubyte[] a = [ 0x12, 0x34, 0x56, 0x78 ];
    uint[]  b = a.to!(uint[]);
    writefln("%(%02x %)", cast(uint[])a);
    writefln("%(%02x %)", cast(ubyte[])b);
}

問題3

ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。

import std;
void func1()
{
    write(x);
}
int x = 5;
void main()
{
    void func1()
    {
        write(x+3);
    }
    int x = 4;
    write(x);
    write(.x);
    func1();
    .func1();
}

番外編

答えが一意に決まらないだろうとの理由で、正式な問題ではなく、番外編としました。
ソースコードをコンパイル、実行すると、どのような出力結果になるでしょうか。
あえてdestroy(c)はコメントアウトしています。

import std;
class C1 {
    this(){  write("1"); }
    ~this(){ write("2"); }
    static this(){  write("3"); }
    static ~this(){ write("4"); }
}
class C2 : C1 {
    this(){  write("5"); }
    ~this(){ write("6"); }
    static this(){  write("7"); }
    static ~this(){ write("8"); }
}
void main()
{
    C2 c = new C2();
    write("9");
//    destroy(c);
}

ここから回答編です。ネタばれ注意!!

問題1の答え

問題1の実行結果
問題1の実行結果
521643

答えの補足

  • scope(exit)は、スコープから抜けるタイミングで実行されます。(3, 4は5, 6よりあとに出力されます)
  • scope(exit)は、例外(exception)が発生しても、呼び出されます。(1が出力されるのは仕様です)
  • scope(exit)が複数呼び出された場合は、呼び出し順の逆から実行されます。(4→3の順で出力されるのは仕様です)

問題2の答え

問題2の実行結果
問題2の実行結果
78563412
12 00 00 00 34 00 00 00 56 00 00 00 78 00 00 00

答えの補足

  • toは、実際にデータの変換を行います。元データとは別にデータが生成されます。
  • キャスト(cast)は、データ変換を行いません。元データを別の型とみなしているだけです。
  • writeflnを使えば、配列の16進数表示も簡潔に書けます。

問題3の答え

問題3の実行結果
問題3の実行結果
4585

答えの補足

  • グローバルとローカルに同じ名前の変数や関数を宣言できます。
  • グローバル側にアクセスしたい場合は、変数名や関数名の前に.をつけます。
  • main関数内のfunc1が参照するxはグローバル側になります。もし、main関数内のfunc1よりも先にint x = 4;が宣言されていれば、ローカル側のxが参照され、問題3の答えは4575となっていました。

番外編の答え

番外編の実行結果
番外編の実行結果
371598462

Online D Editor(2021/12/14現在)での実行結果を正解とさせていただきます。

答えの補足

  • static thisは、mainより先に呼び出されます。
  • クラスに継承関係がある場合、static thisも、thisも基底クラスが先に呼び出されます。
  • クラスに継承関係がある場合、static ~thisも、~thisも派生クラスが先に呼び出されます。
  • static ~thisは対象スレッドの終了時に、~thisはオブジェクト削除のタイミングに呼び出されます。どちらが先に実行されるかの規定はなく、この場合、GC(オブジェクト削除)が最後に実行されたということです。
  • ちなみに、destroyを呼び出せば、~thisがすぐに実行されます。

最後に

普段からD言語を使っている方には、簡単すぎたかもしれません。
問題作成のために、言語仕様をじっくり読んだので、私自身勉強になりました。
第2弾も予定していますので、よろしくお願いします。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0