返回介绍

10.4.2 通过引用传递

发布于 2020-09-09 22:55:49 字数 1467 浏览 1013 评论 0 收藏 0

通过引用传递的参数不会拷贝到子例程区域,相反,一个对原始参数的引用会被传递到子例程。然后子例程可以通过这个引用访问参数数据。通过引用传递的参数必须匹配于等价数据类型。参见5.8.1节,等价类型。而且不允许使用强制类型转换。为了指示通过引用传递的参数,参数声明需要以ref关键字开始。基本语法如下:

subroutine(ref type argument);

例如,上一节的例子可以重写为:

function int crc(ref byte packet[1000:1]);
    for(int j=1; j<=1000; j++) begin
        crc ^= packet[j];
    end
endfunction

注意,在这个例子中,除了加入所需的ref关键字外,没有作任何改变。编译器知道现在packet是通过引用寻址的,然而,无论是在被调用者中还是在调用点上,用户都不需要显式地说明这些引用。也就是说,无论对于哪个版本的crc函数,对它的调用都是相同的:

byte packet1[1000:1];
int k = crc(packet1);  // 无论是通过值传递还是通过引用传递,调用方法是一样的

当通过引用传递参数的时候,调用者与子例程共享参数的相同表示,因此,在调用者内或子例程中对参数所作的任何改变对两者都是可见的。对通过引用传递的变量赋值的语义是:在子例程的外部可以立即(在子例程返回之前)看到变量的变化。只有变量才能通过引用传递,线网则不允许这样做。

通过引用传递的参数必须完全匹配,当通过引用传递参数的时候,不可能有promotion、转换、或自动的强制类型转换。特别地,数组参数必须在类型和所有的维数上完全匹配。固定尺寸的数组不能与动态数组混合,反之亦然。

通过引用传递参数是一个唯一的参数传递限定符,它不同于input、output、或inout。将ref和任何其它的方向限定符结合在一起使用是非法的。例如,下列的声明会导致一个编译错误:

task incr(ref input int a); // 不正确:不能使用ref限定

ref参数类似于一个inout参数,它们的不同之处在于一个inout参数会被拷贝两次:当子例程被调用的时候完成一个真实值到参数的拷贝,当子例程返回的时候完成一个参数到真实值的拷贝。传递对象句柄也没有例外,当它作为ref或inout参数传递的时候具有相似的语义,因此,一个对象句柄的ref除了允许修改对象内容外,它还允许改变对象句柄(例如指定一个新的对象)。

为了保护通过引用传递的参数不被一个子例程修改,可以将const限定符与ref一起使用,用来表明尽管这个参数是通过引用传递,但它是一个只读变量。

task show (const ref byte [] data);
    for (int j = 0; j < data.size; j++)
        $display(data[j]); // 数据可以被读出但不能被修改
endtask

当形式参数作为一个const ref声明的时候,子例程不能改变这个变量,试图改变变量会产生一个编译错误。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文