跳轉到內容

D(程式語言)/d2/指標、傳引用和靜態陣列

25% developed
來自華夏公益教科書,自由的教科書

第 7 課:指標、傳引用和靜態陣列

[編輯 | 編輯原始碼]

本章,你將學習如何在 D 中使用指標和靜態陣列。你還會學習如何在不使用指標的情況下傳引用。課文不會解釋指標和陣列背後的概念,它假設你從 C 或 C++ 中瞭解這些知識。D 還有動態陣列和陣列切片,兩者將在以後的課文中介紹。

入門程式碼

[編輯 | 編輯原始碼]

使用指標

[編輯 | 編輯原始碼]
import std.stdio;

void add_numbers(int* a, int* b)
{
    *a = *a + *b;
}

void main()
{
    int a = 50;
    int* b = &a;
    *b = 30;
    writeln(a);  // 30
    
    // int* error = &50; Error: constant 50 is not an lvalue
    
    int c = 2;
    int d = 2;
    add_numbers(&c, &d);
    writeln(c);  // 4
}

傳引用

[編輯 | 編輯原始碼]

如果你是一位 C++ 程式設計師,你讀到這裡,可能會認為這是比 C++ 引用退步的一步,那麼恭喜你:雖然 D 支援指標,但它也支援更優的解決方案來將變數作為引用傳遞給函式。

import std.stdio;

void add_numbers(ref int a, int b)
{
    a += b;
}

void main()
{
    int c = 2;
    int d = 2;
    add_numbers(c, d);
    writeln(c); // 4

    // add_numbers(4, 2); Error: integer literals are not lvalues and cannot be passed by reference
}

它還專門支援 *輸出引數*

import std.stdio;

void initializeNumber(out int n)
{
    n = 42;
}

void main()
{
    int a;
    initializeNumber(a);
    writeln(a); // 42
}

使用 `out`,在函式開始時,`n` 在 `initializeNumber` 中被預設初始化。

使用靜態陣列

[編輯 | 編輯原始碼]
import std.stdio;

void main()
{
    int[5] a;
    a[0] = 1;
    writeln(a);  // [1, 0, 0, 0, 0]
    
    // a[10] = 3;  Error: Array index 10 is out of bounds
    
    int* ptr_a = &a[0];
    ptr_a[0] = 5;
    ptr_a[4] = 3;
    writeln(a); // [5, 0, 0, 0, 3]
    
    // ptr_a[10] = 3;  // Bad: This memory is not owned by 'a' as it is out of bounds
    // Compiler would allow it, but the result is undefined!

    int[3] b = 3;
    writeln(b);  // [3, 3, 3]
    b[] = 2;
    writeln(b);  // [2, 2, 2]
}

引用和解引用

[編輯 | 編輯原始碼]

D 中的語法與 C 和 C++ 相同。運算子 `&` 獲取物件的引用,而 `*` 解引用。

指標型別

[編輯 | 編輯原始碼]

在 D 中,指向 `typeA` 的指標是

typeA*

宣告一個指標的程式碼是

typeA* identifier;

.

靜態陣列

[編輯 | 編輯原始碼]

靜態陣列具有固定長度。你可以像這樣宣告它們:

byte[10] array_of_ten_bytes;

你也可以這樣做:

byte[2] array_of_two_bytes = [39, 0x3A];

陣列索引從第一個元素的 0 開始。編譯器會在你嘗試訪問索引大於或等於陣列長度的元素時捕獲你。你可以像這樣訪問陣列元素:

my_array[index]

你也可以用單個值填充陣列,使陣列的所有元素都等於該值:

int[7] a = 2;
writeln(a);  // [2, 2, 2, 2, 2, 2, 2]
a[] = 7;
writeln(a);  // [7, 7, 7, 7, 7, 7, 7]

作為函式引數

[編輯 | 編輯原始碼]

看看這段程式碼:

import std.stdio;

void addOne(int[3] arr)
{
    arr[0] += 1;
    // this means arr[0] = arr[0] + 1
}

void main()
{
    int[3] array1 = [1, 2, 3];
    addOne(array1);
    writeln(array1); // [1, 2, 3]
}

輸出是 `[1,2,3]`,而不是 `[2,2,3]`。為什麼?因為靜態陣列在作為函式引數傳遞時會被複制。`addOne` 函式中的 `arr` 只是 `array1` 的一個副本。將程式碼改寫成這樣:

import std.stdio;

void addOne(ref int[3] arr)
{
    arr[0] += 1;
}

void main()
{
    int[3] array1 = [1, 2, 3];
    addOne(array1);
    writeln(array1); // [2, 2, 3]
}
華夏公益教科書