`
com1com4
  • 浏览: 161518 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Delphi笔记(整理)-例程(Routine)

阅读更多
过程和函数统称为例程(routine)
标准过程Exit 可出现在任何过程或函数中,它结束例程的执行,并立即把程序控制返回到例程调用的地方。

一个过程声明有如下格式:
procedure procedureName(parameterList); directives;
localDeclarations;
begin
statements
end;

函数声明和过程声明类似,除了它要指定一个返回值的类似和返回值。函数声明有如下格式:
function functionName(parameterList): returnType; directives;
localDeclarations;
begin
statements
end;
函数名本身也扮演一个特殊的变量,它和内置的变量Result 一样,存储函数的返回值。

Result 和函数名并不是能完全互换的,当函数名出现在赋值语句的左边时,编译器假设它
用来跟踪(存储)返回值(就像Result);在任何其它情况下,编译器把它解释为对它的递归调用。而对
Result,它可以作为变量用在运算、类型转换、集合构造器、索引以及调用其它例程。

只要启用了扩展语法({$X+}),Result 在每个函数中被隐含声明,不要试图重新声明它。
若还没有给Result 或函数名赋值,程序就结束了,则函数的返回值没有被定义(undefined)。

在声明过程或函数时,你可以使用下面的指示字之一来指明调用约定:register、pascal、cdecl、stdcall
以及safecall。比如,
function MyFunction(X, Y: Real): Real; cdecl;
...
调用约定决定了参数被传递给例程的顺序,它们也影响从堆栈中删除参数、传递参数时寄存器的使用,
以及错误和异常处理。默认的调用约定是register。
• register 和pascal 调用从左到右传递参数,也就是说,最左边的参数最早被计算并传递,最右边的
参数最后被计算和传递;cdecl、stdcall 和safecall 调用从右到左传递参数;
• 除了cdecl 调用,过程和函数在返回之前从堆栈中移除参数,而使用cdecl,当调用返回时,调用者
从堆栈中移除参数;
• register 调用能使用多达3 个CPU 寄存器传递参数,而其它调用则全部使用堆栈传递参数;
• safecall 调用实现了异常“防火墙”,在Windows 下,它实现了进程间COM 错误通知。

默认的register 调用是最有效的,因为它通常避免了要创建堆栈结构(stack frame)(访问公布属性的方
法必须使用register);当调用来自C/C++编写的共享库中的函数时,cdecl 是有用的;通常,当调用外部
代码时,推荐使用stdcall 和safecall。在Windows 中,系统API 使用stdcall 和safecall,其它操作系统
通常使用cdecl(注意,stdcall 比cdecl 更有效)。声明双重接口的方法必须使用safecall;保留pascal 调用是为了向后兼容性。

指示字near、far 和export 用在16 位Windows 编程中,它们对32 位程序没有影响,保留它们是为了向后兼容性。

在声明过程或函数时,用forward 指示字取代例程块(包括局部变量声明和语句),比如,
function Calculate(X, Y: Integer): Real; forward;

forward 声明的目的是把过程或函数标志符的作用域提前,这允许在它被实际定义之前,其它过程和函
数可以进行调用。除了能使你更灵活地组织代码外,forward 声明对相互递归调用(mutual recursion)有
时是必须的。

在声明过程或函数时,用external 指示字取代例程块,能允许你调用和程序分开编译的例程。外部例程
可以来自目标文件或动态调入库(dynamically loadable library)。
当导入一个带有可变数目参数的C++函数时,要使用varargs 指示字。比如,
function printf(Format: PChar): Integer; cdecl; varargs;
varargs 指示字只能用于外部例程,并且只能使用cdecl 调用约定。

要调用目标文件中的例程,首先要使用$L(或$LINK)编译器指示字把目标文件链接到你的程序中。比
如,
在Windows 下: {$L BLOCK.OBJ}
在Linux 下: {$L block.o}
把BLOCK.OBJ(Windows)或block.o (Linux)链接到程序或它所在的单元。然后,声明你想调用的
函数和过程:
procedure MoveWord(var Source, Dest; Count: Integer); external;
procedure FillWord(var Dest; Data: Integer; Count: Integer); external;
现在,你就能调用来自BLOCK.OBJ 或block.o 的MoveWord 和FillWord 例程了。
像上面的声明,经常用来访问由汇编语言编写的外部例程,你也可以直接在Object Pascal 源代码中放置
汇编语言写的例程。

要从一个动态调入库(.so 或.DLL)导入例程,把如下格式的指示字
external stringConstant;
放在一个正常的过程头或函数头的尾部。这里,stringConstant 是用单引号括起来的库文件的名称。比如,
在Windwos 下
function SomeFunction(S: string): string; external ’strlib.dll’;
从strlib.dll 导入一个叫做SomeFunction 的函数。
在Linux 下,
function SomeFunction(S: string): string; external ’strlib.so’;
从strlib.so 导入一个叫做SomeFunction 的函数。
在导入例程时,它的名称可以和库中的名称不同。如果你这样做,在external 指示字中指定它的原始名
称。
external stringConstant1 name stringConstant2;
这里,第一个stringConstant 给出了库文件的名称,第二个stringConstant 是例程的原始名称。
在Windows 下:比如,下面的声明从user32.dll(Windows API 的一部分)导入一个函数。
function MessageBox(HWnd: Integer; Text, Caption: PChar; Flags: Integer): Integer;
stdcall; external ’user32.dll’ name ’MessageBoxA’;
函数的原始名称是MessageBoxA,但导入后的名称是MessageBox。
你可以使用一个数字代替名称,来指定你要导入的例程:
external stringConstant index integerConstant;
这里,integerConstant 是输出表(export table)中例程的索引。
在Linux 下:比如,下面的声明从libc.so.6 导入一个标准系统函数。
function OpenFile(const PathName: PChar; Flags: Integer): Integer; cdecl;
external ’libc.so.6’ name ’open’;
函数的原始名称是open,但导入后的名称是OpenFile。
在你的导入声明中,要保证例程的名称没有拼写错误,并且大小写一致。但在以后调用这些例程时,它
们是不区分大小写的。

重载例程必须使用overload 指示字,并且它们有不同的参数列表。

当重载例程被声明为forward、或在单元的接口部分声明时,在它的定义声明部分必须重新列出它的参数。

参数以下面几种方式进行分类:
• 每个参数分为value(数值参数)、variable(变量参数)、constant(常量参数)或out(out 参数),
默认是数值参数。关键字var、const 以及out 分别表示变量参数、常量参数和out 参数。
• 数值参数总是有类型的,而常量参数、变量参数和out 参数既可以是有类型的,也可以是无类型的。
• 数组参数有特殊规则。
文件类型以及包含文件的结构类型(的实例)只能作为变量参数传递。

数值参数通过数值传递,而变量参数通过引用传递。

如果例程声明了一个var 参数,你必须给它传递一个能被赋值的表达式,也就是一个变量、类型化常量
(typed constant,在{$J+}状态下)、dereferenced 指针、字段或者索引变量(indexed variable)

当使用out 参数时,传给例程的引用参数的初始值被忽略。out 参数只是为了输出,也就是说,它告诉
函数或过程在哪里存储输出,但不提供任何输入。
out 参数经常用在分布式对象模型中,比如COM 和CORBA。而且,当向函数或过程传递未初始化的变
量时,你应当使用out 参数。

特殊标志符OpenString 能用于声明可变长度的短字符串参数:
procedure Check(S: OpenString);
当编译器指示字{$H-}和{$P+}都起作用时,在声明参数时关键字string 等同于OpenString。
短字符串、OpenString、$H 和$P 是为了向后兼容性。在新代码中,使用长字符串来避免这种情况

开放数组参数遵循下列规则:
• 元素的下标总是从0 开始,第一个是0,第二个是1,依此类推。标准函数Low 和High 返回0 和
Length-1。SizeOf 函数返回传给例程的实际数组的大小;
• 它们只能通过元素进行访问,不允许给整个开放数组赋值;
• 它们只能被当作开放数组参数或无类型var 参数传给其它过程和函数,它们不能传给SetLength 函
数;
• 你可以传递一个变量而不是数组,变量的类型就是开放数组的基础类型,它被当作一个长度为1 的
数组。

Variant 开放数组参数允许你向一个过程或函数传递由不同类型的元素构成的数组。要定义这样一个例
程,指定array of const 作为参数的类型,这样
procedure DoSomething(A: array of const);
声明了一个叫做DoSomething 的过程,它能接收不同类型的数组。
array of const 结构等同于array of TVarRec。TVarRec 在System 单元定义,表示一个拥有变体部分的记
录,它能存储整数、布尔、字符、实数、字符串、指针、类、类引用、接口和变体类型的值。TVarRec
记录的VType 字段指示数组中每个元素的类型。一些类型以指针而不是以数值形式进行传递,特别是,
长字符串以指针类型传递,必须被转换为string。

有默认值的参数必须出现在参数列表的最后

在过程类型中指定的默认值会覆盖实际例程中指定的默认值。所以,给出下面的声明
type TResizer = function(X: Real; Y: Real = 1.0): Real;
function Resizer(X: Real; Y: Real = 2.0): Real;
var
F: TResizer;
N: Real;
语句
F := Resizer;
F(N);
导致(N, 1.0)传给Resizer。

默认参数局限于能被常量表达式所表示的值,所以,动态数组、过程、类、类引用或者接口类型的参数
除了nil 外不能给它们指定默认值,而记录、变体、文件、静态数组和对象类型则根本不能指定默认值。

若在重载例程中使用默认参数,要避免引起歧义。

开放数组构造器和集合构造器类似,是由逗号隔开的表达式序列,并且被一对中括号包围。

开放数组构造器只能当作数值参数或常量参数传递。构造器中的表达式必须和数组参数的基础类型是赋
值兼容的。对于Variant 开放数组参数,表达式可以是不同的类型。
分享到:
评论

相关推荐

    msp430f5438--例程--综合应用.rar

    msp430f5438--例程--综合应用.rar msp430f5438--例程--综合应用.rar msp430f5438--例程--综合应用.rar msp430f5438--例程--综合应用.rar msp430f5438--例程--综合应用.rar

    msp430f5438--例程--渐进提高.rar

    msp430f5438--例程--渐进提高.rar msp430f5438--例程--渐进提高.rar msp430f5438--例程--渐进提高.rar msp430f5438--例程--渐进提高.rar msp430f5438--例程--渐进提高.rar

    msp430f5438--例程--基础入门.rar

    msp430f5438--例程--基础入门.rar msp430f5438--例程--基础入门.rar msp430f5438--例程--基础入门.rar msp430f5438--例程--基础入门.rar

    轻松学PIC--例程全集

    《轻松学PIC--例程全集》是一份旨在帮助初学者和进阶者掌握PIC微控制器编程的资源集合。这份压缩包文件包含了丰富的实例代码,是学习和理解PIC微控制器工作原理、应用以及编程的宝贵资料。PIC微控制器是Microchip ...

    中景园电子0.96OLED显示屏-C51系列测试程序 IIC-例程+SPI-例程工程源码.zip

    中景园电子0.96OLED显示屏_C51系列测试程序 IIC_例程+SPI_例程工程源码: 中景园电子0.96OLED显示屏_C51系列_IIC_例程推荐使用 中景园电子0.96OLED显示屏_C51系列_IIC_例程推荐使用.zip 中景园电子0.96OLED显示屏_C51...

    ZigBee 各类传感器模块-例程及使用手册

    每种传感器均配套裸机部分例程及协议栈例程。部分没有配套协议栈例程的传感器,请参考实战演练中其他传感器移植方法自行移植。 部分传感器只配套zibgee平台代码,蓝牙4.0平台暂时没有配套,请从zigbee代码包中提取...

    Linux学习笔记14-EPIT 定时器实验例程

    Linux学习笔记14---EPIT 定时器实验例程

    Linux学习笔记13-GPIO 中断实验例程

    Linux学习笔记13---GPIO 中断实验例程

    2.OneNET-V3.2-OneNET-裸机-基础例程_stm32_

    标题 "2.OneNET-V3.2-OneNET-裸机-基础例程_stm32_" 指示了这是一个基于STM32微控制器的OneNET平台的V3.2版本的基础程序实例。OneNET是中国移动物联网公司提供的一种云服务平台,它支持多种物联网设备的数据接入,...

    南昌航空大学安卓程序设计课件-例程.zip

    南昌航空大学安卓程序设计课件-例程.zip

    arduino uno例程

    例程1-Hello World! 例程2-LED 闪烁 例程3-PWM调光 例程4-广告灯 例程5-交通灯 例程6-按键控制 例程7-抢答器 例程8-蜂鸣器 例程9-模拟值 例程10-光控声音 例程11-感光灯 例程12-温度传感 例程13-倾斜开关 例程14-...

    python操作海康威视相机------例程由海康官方提供 感谢海康工作人员

    Python操作海康威视相机是基于其官方提供的SDK(Software Development Kit)进行的,这个SDK主要为开发者提供了接口,使得我们可以用编程的方式控制海康威视的网络相机,包括视频流获取、图像抓拍、录像回放等功能。...

    Delphi6编程指南例程.zip

    Delphi 6编程指南例程.zip是一个包含与Delphi 6开发相关的实例代码和教程的压缩文件。Delphi 6是Borland公司(后来被Embarcadero Technologies收购)在2002年推出的一款集成开发环境(IDE),它基于Pascal语言,并...

    S7-1200 例程合集

    《S7-1200 例程合集》是一个专为S7-1200 PLC用户设计的资源集合,包含了丰富的实例程序,旨在帮助用户更好地理解和掌握西门子S7-1200系列可编程逻辑控制器的编程与应用。这个资料包是由TIA博途V14SP1软件进行编写的...

    Delphi智能在线升级例程

    "Delphi智能在线升级例程"是开发者们经常遇到的一个重要课题,特别是在开发需要定期更新的应用程序时。这个例程提供了自动更新功能,使得用户可以无缝地获取应用的最新版本,而无需手动下载和安装。 在这个例程中,...

    ADS通讯-例程

    例程包含上位机、下位机和例程说明三部分,并且涉及到的知识点都做了详细的注释。 功能包括: ADS通讯、多媒体定时器、线程的应用。训练技能以ADS通讯为主。 例程使用请跳转至...

    RN7213是ARM Cortex-M0内核的电表SOC芯片带LCD驱动 采样速度快,开发例程齐全,有参考方案-RN821x_RN831x_RN721x应用笔记004-主要模块使用说明v1.2.zip

    在本应用笔记中,我们将深入探讨RN7213的主要模块及其使用方法。 1. **ARM Cortex-M0内核**:Cortex-M0是ARM公司推出的低功耗、高性能的微控制器核心,适合于资源有限的嵌入式应用。其精简的结构和高效的指令集使得...

    GPS模块资料-代码-例程-讲解

    包括封装库,原理,数据流格式,stm32源代码,原理图

    ARM嵌入式系统应用技术笔记例程-LPC23XX

    技术笔记上册例程部分涵盖了LPC23XX的初始化、GPIO控制、串行通信、中断处理、ADC和DAC操作等多个方面。通过这些实例,开发者可以学习如何设置和操作微控制器的各个功能模块。 1. **初始化程序**:通常包括复位、...

    7.OneNET-V3.2-扩展例程_:麒麟座开发板Onenet扩展例程_

    《麒麟座开发板Onenet扩展例程:官方代码解析与实战指南》 在现代物联网(IoT)领域,OneNET平台作为一个强大的云服务平台,为开发者提供了便捷的数据接入、存储、分析以及应用开发的能力。麒麟座开发板作为硬件...

Global site tag (gtag.js) - Google Analytics