跳转至内容

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];

数组从数字零开始索引,第一个元素的索引为零。如果尝试访问索引大于或等于该数组长度的元素,编译器会捕获它。您可以像这样访问数组的元素:

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]
}
华夏公益教科书