热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

delphi与变长参数——开放数组(1)

与CC++不同,Delphi中是通过可变类型(TVarRec)的开放数组来指定变长参数的。其实这里已经不能称“变长参数”了,因为实际上只传递了一个参数,只是该参数是由多个
 

       与C/C++不同,Delphi中是通过可变类型(TVarRec)的开放数组来指定变长参数的。其实这里已经不能称“变长参数”了,因为实际上只传递了一个参数,只是该参数是由多个基础类型数据构成的一个开放数组。Delphi使用开放数组来容纳不定数目的参数,使用可变类型(TVarRec)表示各种类型数据,因此二者的结合可以达到C/C++中变长参数的功能。

       TVarRec是一个记录类型,该记录的VType字段标志记录值的类型,如整数、布尔、字符、实数、字符串、指针、类、类引用、接口、变体等。【注1】

//这是定义在 System 单元关于数据类型的一个结构:
TVarRec = record
  case Byte of
    vtInteger:    (VInteger: Integer; VType: Byte);
    vtBoolean:    (VBoolean: Boolean);
    vtChar:       (VChar: Char);
    vtExtended:   (VExtended: PExtended);
    vtString:     (VString: PShortString);
    vtPointer:    (VPointer: Pointer);
    vtPChar:      (VPChar: PChar);
    vtObject:     (VObject: TObject);
    vtClass:      (VClass: TClass);
    vtWideChar:   (VWideChar: WideChar);
    vtPWideChar:  (VPWideChar: PWideChar);
    vtAnsiString: (VAnsiString: Pointer);
    vtCurrency:   (VCurrency: PCurrency);
    vtVariant:    (VVariant: PVariant);
    vtInterface:  (VInterface: Pointer);
    vtWideString: (VWideString: Pointer);
    vtInt64:      (VInt64: PInt64);
end;

      

       那么开放数组又是什么?关于开放数组,官方文档给出的解释是:

(1)Object Pascal has an “open array” construct that permits an array of unspecified size to be passed to a function.

面向对象Pascal有一个开放数组的概念允许向一个方法传递未指定大小的数组。

(2)an Object Pascal function that has an open array parameter can be called by explicitly passing both the pointer to the first element of an array and the value of the last index (number of array elements, minus one).

一个面向对象的含有开放数组参数的Pascal函数能通过传递数组的第一个元素的地址和最后一个元素的索引(即数组大小减1)来调用。

 

//官方例子
//Object Pascal声明
function  Mean(Data:  array of  Double): Extended;
//Pascal调用
Result := Mean([3.1, 4.4, 5.6]);
//官方例子
//C++声明
Extended  __fastcall  Mean( const double  * Data,  const int  Data_Size);
//C++调用
double  d[] = { 3.1, 4.4, 5.6 } ; 
return  Mean(d, 2) ;

 

       看了官方文档还是一头雾水,根本就没解释什么是开放数组。好像开放数组与动态数组是一样的嘛!在Delphi中,数组类型有静态数组(array[0..1024] of integer)、动态数组(array of integer)两类。关于动态数组,官方文档给出的解释是:

(3)Dynamic arrays do not have a fixed size or length. Instead, memory for a dynamic array is reallocated when you assign a value to the array or pass it to the SetLength procedure.

动态数组没有固定大小或长度。你可以通过给动态数组赋值或使用SetLength方法给动态数组重新分配内存。

//定义动态数组变量
var MyFlexibleArray: array of Real;
//分配内存
SetLength(MyFlexibleArray, 20);

       动态数组变量是一个隐式指针,它是由引用计数技术进行管理的。其使用方法这里不多说,这里看下官方给出的Note。

(4)Note: In some function and procedure declarations, array parameters are represented as array of baseType, without any index types specified.

注意:在一些函数或过程的声明中,数组参数被描述成没有索引类型标识符的“array of baseType”形式。

//官方例子
function CheckStrings(A: array of string): Boolean;

(5)This indicates that the function operates on all arrays of the specified base type, regardless of their size, how they are indexed, or whether they are allocated statically or dynamically.

这表明这个函数可以操作(即接受实参)所有指定的baseType类型的数组,无论该数组的大小是多少、该数组是如何索引的和该数组是静态分配还是动态分配。

       其实这里说的就是开放数组参数,这该死的官方文档,它就是不指明一下。

       网上文章在介绍动态数组时都是用“array of Type”进行定义;而在讨论开放数组时又说“array of Type”定义的是开放数组,通过“Type TArr=array of Type;var a:TArr;”定义的才是动态数组。经过大量搜索阅读,我的理解是:在函数声明中使用“array of Type”定义形参的是开放数组;而在其他位置使用“array of Type”定义数组变量的是动态数组。

       其实很多时候,只有在讨论函数的数组参数时才有开放数组一说,很多时候也是以开放数组参数进行阐述的。这也与官方文档给出的解释一致:开放数组是在给方法传递数组参数时的一个概念。静态数组和动态数组都可以传递给开放数组参数,Delphi隐式(自动地)传递它们的长度。【注2】

       开放数组参数实际上是一个包含指向数组第一个元素地址的指针和调整后以0开始的数组元素的最大索引值(即数组长度减1)的结合物。针对前面声明Mean函数,它实际上的参数列表如下所示:【注3】

function Mean(PData:Pointer; High: Integer): Extended;

这一点与前面官方文档给出的第(2)条解释一致,只是Delphi使用开放数组参数将这个细节给隐藏了,我们只需将静态或动态数组的首地址(即数组变量名)传递给函数,对于静态数组,编译器直接传递数组大小(减1),对于动态数组,编译器自动生成代码以便在运行时获取动态数组的High值。

 

 

       下接delphi与变长参数——开放数组(2)。

 

 

 

 


注1:更多有关TVarRec的内容请参考http://docwiki.embarcadero.com/VCL/en/System.TVarRec

注2:Both static and dynamic arrays may be passed to subroutines as parameters. If the array parameter definition has no range (ie, a dynamic array type), then you must, paradoxically pass a static array as a parameter. Such an array is referred to as an Open array. Delphi passes the length as a hidden parameter to the subroutine.(详情请参考http://www.delphibasics.co.uk/RTL.asp?Name=Array )

注3:An open array parameter is actually acombination of two parameters, a pointer, which contains the address of the start of the array, and an integer, which contains the High value, adjusted for a zero base.(详情请参考http://rvelthuis.de/articles/articles-openarr.html的Internals一节)

 

 

 

 

 


推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
author-avatar
潇潇沐林风_921
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有