导航:首页 > 源码编译 > pidc编译器

pidc编译器

发布时间:2023-09-09 21:00:06

‘壹’ PLC电控是什么东西如何解释

1、PLC即可编程控制器(Programmable logic Controller,是指以计算机技术为基础的新型工业控制装置。在1987年国际电工委员会(International Electrical Committee)颁布的PLC标准草案中对PLC做了如下定义:

“PLC是一种专门为在工业环境下应用而设计的数字运算操作的电子装置。它采用可以编制程序的存储器,用来在其内部存储执行逻辑运算、顺序运算、计时、计数和算术运算等操作的指令,并能通过数字式或模拟式的输入和输出,控制各种类型的机械或生产过程。PLC及其有关的外围设备都应该按易于与工业控制系统形成一个整体,易于扩展其功能的原则而设计。”

PLC的特点

2.1可靠性高,抗干扰能力强
高可靠性是电气控制设备的关键性能。PLC由于采用现代大规模集成电路技术,采用严格的生产工艺制造,内部电路采取了先进的抗干扰技术,具有很高的可靠性。例如三菱公司生产的F系列PLC平均无故障时间高达30万小时。一些使用冗余CPU的PLC的平均无故障工作时间则更长。从PLC的机外电路来说,使用PLC构成控制系统,和同等规模的继电接触器系统相比,电气接线及开关接点已减少到数百甚至数千分之一,故障也就大大降低。此外,PLC带有硬件故障自我检测功能,出现故障时可及时发出警报信息。在应用软件中,应用者还可以编入外围器件的故障自诊断程序,使系统中除PLC以外的电路及设备也获得故障自诊断保护。这样,整个系统具有极高的可靠性也就不奇怪了。

2.2配套齐全,功能完善,适用性强
PLC发展到今天,已经形成了大、中、小各种规模的系列化产品。可以用于各种规模的工业控制场合。除了逻辑处理功能以外,现代PLC大多具有完善的数据运算能力,可用于各种数字控制领域。近年来PLC的功能单元大量涌现,使PLC渗透到了位置控制、温度控制、CNC等各种工业控制中。加上PLC通信能力的增强及人机界面技术的发展,使用PLC组成各种控制系统变得非常容易。

2.3易学易用,深受工程技术人员欢迎
PLC作为通用工业控制计算机,是面向工矿企业的工控设备。它接口容易,编程语言易于为工程技术人员接受。梯形图语言的图形符号与表达方式和继电器电路图相当接近,只用PLC的少量开关量逻辑控制指令就可以方便地实现继电器电路的功能。为不熟悉电子电路、不懂计算机原理和汇编语言的人使用计算机从事工业控制打开了方便之门。

2.4系统的设计、建造工作量小,维护方便,容易改造
PLC用存储逻辑代替接线逻辑,大大减少了控制设备外部的接线,使控制系统设计及建造的周期大为缩短,同时维护也变得容易起来。更重要的是使同一设备经过改变程序改变生产过程成为可能。这很适合多品种、小批量的生产场合。

2.5体积小,重量轻,能耗低
以超小型PLC为例,新近出产的品种底部尺寸小于100mm,重量小于150g,功耗仅数瓦。由于体积小很容易装入机械内部,是实现机电一体化的理想控制设备。

3. PLC的应用领域
目前,PLC在国内外已广泛应用于钢铁、石油、化工、电力、建材、机械制造、汽车、轻纺、交通运输、环保及文化娱乐等各个行业,使用情况大致可归纳为如下几类。

3.1开关量的逻辑控制
这是PLC最基本、最广泛的应用领域,它取代传统的继电器电路,实现逻辑控制、顺序控制,既可用于单台设备的控制,也可用于多机群控及自动化流水线。如注塑机、印刷机、订书机械、组合机床、磨床、包装生产线、电镀流水线等。

3.2模拟量控制
在工业生产过程当中,有许多连续变化的量,如温度、压力、流量、液位和速度等都是模拟量。为了使可编程控制器处理模拟量,必须实现模拟量(Analog)和数字量(Digital)之间的A/D转换及D/A转换。PLC厂家都生产配套的A/D和D/A转换模块,使可编程控制器用于模拟量控制。

3.3运动控制
PLC可以用于圆周运动或直线运动的控制。从控制机构配置来说,早期直接用于开关量I/O模块连接位置传感器和执行机构,现在一般使用专用的运动控制模块。如可驱动步进电机或伺服电机的单轴或多轴位置控制模块。世界上各主要PLC厂家的产品几乎都有运动控制功能,广泛用于各种机械、机床、机器人、电梯等场合。

3.4过程控制
过程控制是指对温度、压力、流量等模拟量的闭环控制。作为工业控制计算机,PLC能编制各种各样的控制算法程序,完成闭环控制。PID调节是一般闭环控制系统中用得较多的调节方法。大中型PLC都有PID模块,目前许多小型PLC也具有此功能模块。PID处理一般是运行专用的PID子程序。过程控制在冶金、化工、热处理、锅炉控制等场合有非常广泛的应用。

3.5数据处理
现代PLC具有数学运算(含矩阵运算、函数运算、逻辑运算)、数据传送、数据转换、排序、查表、位操作等功能,可以完成数据的采集、分析及处理。这些数据可以与存储在存储器中的参考值比较,完成一定的控制操作,也可以利用通信功能传送到别的智能装置,或将它们打印制表。数据处理一般用于大型控制系统,如无人控制的柔性制造系统;也可用于过程控制系统,如造纸、冶金、食品工业中的一些大型控制系统。

3.6通信及联网
PLC通信含PLC间的通信及PLC与其它智能设备间的通信。随着计算机控制的发展,工厂自动化网络发展得很快,各PLC厂商都十分重视PLC的通信功能,纷纷推出各自的网络系统。新近生产的PLC都具有通信接口,通信非常方便。

4. PLC的国内外状况

世界上公认的第一台PLC是1969年美国数字设备公司(DEC)研制的。限于当时的元器件条件及计算机发展水平,早期的PLC主要由分立元件和中小规模集成电路组成,可以完成简单的逻辑控制及定时、计数功能。20世纪70年代初出现了微处理器。人们很快将其引入可编程控制器,使PLC增加了运算、数据传送及处理等功能,完成了真正具有计算机特征的工业控制装置。为了方便熟悉继电器、接触器系统的工程技术人员使用,可编程控制器采用和继电器电路图类似的梯形图作为主要编程语言,并将参加运算及处理的计算机存储元件都以继电器命名。此时的PLC为微机技术和继电器常规控制概念相结合的产物。

20世纪70年代中末期,可编程控制器进入实用化发展阶段,计算机技术已全面引入可编程控制器中,使其功能发生了飞跃。更高的运算速度、超小型体积、更可靠的工业抗干扰设计、模拟量运算、PID功能及极高的性价比奠定了它在现代工业中的地位。20世纪80年代初,可编程控制器在先进工业国家中已获得广泛应用。这个时期可编程控制器发展的特点是大规模、高速度、高性能、产品系列化。这个阶段的另一个特点是世界上生产可编程控制器的国家日益增多,产量日益上升。这标志着可编程控制器已步入成熟阶段。

20世纪末期,可编程控制器的发展特点是更加适应于现代工业的需要。从控制规模上来说,这个时期发展了大型机和超小型机;从控制能力上来说,诞生了各种各样的特殊功能单元,用于压力、温度、转速、位移等各式各样的控制场合;从产品的配套能力来说,生产了各种人机界面单元、通信单元,使应用可编程控制器的工业控制设备的配套更加容易。目前,可编程控制器在机械制造、石油化工、冶金钢铁、汽车、轻工业等领域的应用都得到了长足的发展。

我国可编程控制器的引进、应用、研制、生产是伴随着改革开放开始的。最初是在引进设备中大量使用了可编程控制器。接下来在各种企业的生产设备及产品中不断扩大了PLC的应用。目前,我国自己已可以生产中小型可编程控制器。上海东屋电气有限公司生产的CF系列、杭州机床电器厂生产的DKK及D系列、大连组合机床研究所生产的S系列、苏州电子计算机厂生产的YZ系列等多种产品已具备了一定的规模并在工业产品中获得了应用。此外,无锡华光公司、上海乡岛公司等中外合资企业也是我国比较着名的PLC生产厂家。可以预期,随着我国现代化进程的深入,PLC在我国将有更广阔的应用天地。

5. PLC未来展望
21世纪,PLC会有更大的发展。从技术上看,计算机技术的新成果会更多地应用于可编程控制器的设计和制造上,会有运算速度更快、存储容量更大、智能更强的品种出现;从产品规模上看,会进一步向超小型及超大型方向发展;从产品的配套性上看,产品的品种会更丰富、规格更齐全,完美的人机界面、完备的通信设备会更好地适应各种工业控制场合的需求;从市场上看,各国各自生产多品种产品的情况会随着国际竞争的加剧而打破,会出现少数几个品牌垄断国际市场的局面,会出现国际通用的编程语言;从网络的发展情况来看,可编程控制器和其它工业控制计算机组网构成大型的控制系统是可编程控制器技术的发展方向。目前的计算机集散控制系统DCS(Distributed

Control

System)中已有大量的可编程控制器应用。伴随着计算机网络的发展,可编程控制器作为自动化控制网络和国际通用网络的重要组成部分,将在工业及工业以外的众多领域发挥越来越大的作用。

1 PLC基础知识

1.1 PLC的发展历程

在工业生产过程中,大量的开关量顺序控制,它按照逻辑条件进行顺序动作,并按照逻辑关系进行连锁保护动作的控制,及大量离散量的数据采集。传统上,这些功能是通过气动或电气控制系统来实现的。1968年美国GM(通用汽车)公司提出取代继电气控制装置的要求,第二年,美国数字公司研制出了基于集成电路和电子技术的控制装置,首次采用程序化的手段应用于电气控制,这就是第一代可编程序控制器,称Programmable

Controller(PC)。

个人计算机(简称PC)发展起来后,为了方便,也为了反映可编程控制器的功能特点,可编程序控制器定名为Programmable

Logic Controller(PLC)。

上世纪80年代至90年代中期,是PLC发展最快的时期,年增长率一直保持为30~40%。在这时期,PLC在处理模拟量能力、数字运算能力、人机接口能力和网络能力得到大幅度提高,PLC逐渐进入过程控制领域,在某些应用上取代了在过程控制领域处于统治地位的DCS系统。

PLC具有通用性强、使用方便、适应面广、可靠性高、抗干扰能力强、编程简单等特点。PLC在工业自动化控制特别是顺序控制中的地位,在可预见的将来,是无法取代的。

1.2 PLC的构成

从结构上分,PLC分为固定式和组合式(模块式)两种。固定式PLC包括CPU板、I/O板、显示面板、内存块、电源等,这些元素组合成一个不可拆卸的整体。模块式PLC包括CPU模块、I/O模块、内存、电源模块、底板或机架,这些模块可以按照一定规则组合配置。

1.3 CPU的构成

CPU是PLC的核心,起神经中枢的作用,每套PLC至少有一个CPU,它按PLC的系统程序赋予的功能接收并存贮用户程序和数据,用扫描的方式采集由现场输入装置送来的状态或数据,并存入规定的寄存器中,同时,诊断电源和PLC内部电路的工作状态和编程过程中的语法错误等。进入运行后,从用户程序存贮器中逐条读取指令,经分析后再按指令规定的任务产生相应的控制信号,去指挥有关的控制电路。

CPU主要由运算器、控制器、寄存器及实现它们之间联系的数据、控制及状态总线构成,CPU单元还包括外围芯片、总线接口及有关电路。内存主要用于存储程序及数据,是PLC不可缺少的组成单元。

在使用者看来,不必要详细分析CPU的内部电路,但对各部分的工作机制还是应有足够的理解。CPU的控制器控制CPU工作,由它读取指令、解释指令及执行指令。但工作节奏由震荡信号控制。运算器用于进行数字或逻辑运算,在控制器指挥下工作。寄存器参与运算,并存储运算的中间结果,它也是在控制器指挥下工作。

CPU速度和内存容量是PLC的重要参数,它们决定着PLC的工作速度,IO数量及软件容量等,因此限制着控制规模。

1.4 I/O模块

PLC与电气回路的接口,是通过输入输出部分(I/O)完成的。I/O模块集成了PLC的I/O电路,其输入暂存器反映输入信号状态,输出点反映输出锁存器状态。输入模块将电信号变换成数字信号进入PLC系统,输出模块相反。I/O分为开关量输入(DI),开关量输出(DO),模拟量输入(AI),模拟量输出(AO)等模块。

常用的I/O分类如下:

开关量:按电压水平分,有220VAC、110VAC、24VDC,按隔离方式分,有继电器隔离和晶体管隔离。

模拟量:按信号类型分,有电流型(4-20mA,0-20mA)、电压型(0-10V,0-5V,-10-10V)等,按精度分,有12bit,14bit,16bit等。

除了上述通用IO外,还有特殊IO模块,如热电阻、热电偶、脉冲等模块。

按I/O点数确定模块规格及数量,I/O模块可多可少,但其最大数受CPU所能管理的基本配置的能力,即受最大的底板或机架槽数限制。

1.5 电源模块

PLC电源用于为PLC各模块的集成电路提供工作电源。同时,有的还为输入电路提供24V的工作电源。电源输入类型有:交流电源(220VAC或110VAC),直流电源(常用的为24VDC)。

1.6 底板或机架

大多数模块式PLC使用底板或机架,其作用是:电气上,实现各模块间的联系,使CPU能访问底板上的所有模块,机械上,实现各模块间的连接,使各模块构成一个整体。

1.7 PLC系统的其它设备

1.7.1

编程设备:编程器是PLC开发应用、监测运行、检查维护不可缺少的器件,用于编程、对系统作一些设定、监控PLC及PLC所控制的系统的工作状况,但它不直接参与现场控制运行。小编程器PLC一般有手持型编程器,目前一般由计算机(运行编程软件)充当编程器。也就是我们系统的上位机。

1.7.2 人机界面:最简单的人机界面是指示灯和按钮,目前液晶屏(或触摸屏)式的一体式操作员终端应用越来越广泛,由计算机(运行组态软件)充当人机界面非常普及。

1.8 PLC的通信联网

依靠先进的工业网络技术可以迅速有效地收集、传送生产和管理数据。因此,网络在自动化系统集成工程中的重要性越来越显着,甚至有人提出"网络就是控制器"的观点说法。

PLC具有通信联网的功能,它使PLC与PLC

之间、PLC与上位计算机以及其他智能设备之间能够交换信息,形成一个统一的整体,实现分散集中控制。多数PLC具有RS-232接口,还有一些内置有支持各自通信协议的接口。PLC的通信现在主要采用通过多点接口(MPI)的数据通讯、PROFIBUS

或工业以太网进行联网。

2 PLC控制系统的设计基本原则
2.1 最大限度的满足被控对象的控制要求。
2.2 在满足控制要求的前提下,力求使控制系统简单、经济、使用和维护方便。
2.3 保证控制系统安全可靠。
2.4 考虑到生产的发展和工艺的改进在选择PLC容量时应适当留有余量。
3 PLC软件系统及常用编程语言

3.1 PLC软件系统由系统程序和用户程序两部分组成。系统程序包括监控程序、编译程序、诊断程序等,主要用于管理全机、将程序语言翻译成机器语言,诊断机器故障。系统软件由PLC厂家提供并已固化在EPROM中,不能直接存取和干预。用户程序是用户根据现场控制要求,用PLC的程序语言编制的应用程序(也就是逻辑控制)用来实现各种控制。STEP7是用于SIMATIC可编程逻辑控制器组态和编程的标准软件包,也就是用户程序,我们就是使用STEP7来进行硬件组态和逻辑程序编制,以及逻辑程序执行结果的在线监视。

3.2 PLC提供的编程语言

3.2.1 标准语言梯形图语言也是我们最常用的一种语言,它有以下特点

3.2.1.1 它是一种图形语言,沿用传统控制图中的继电器触点、线圈、串联等术语和一些图形符号构成,左右的竖线称为左右母线。

3.2.1.2 梯形图中接点(触点)只有常开和常闭,接点可以是PLC输入点接的开关也可以是PLC内部继电器的接点或内部寄存器、计数器等的状态。

3.2.1.3 梯形图中的接点可以任意串、并联,但线圈只能并联不能串联。

3.2.1.4 内部继电器、计数器、寄存器等均不能直接控制外部负载,只能做中间结果供CPU内部使用。

3.2.1.5 PLC是按循环扫描事件,沿梯形图先后顺序执行,在同一扫描周期中的结果留在输出状态暂存器中所以输出点的值在用户程序中可以当做条件使用。

3.2.2 语句表语言,类似于汇编语言。

3.2.3 逻辑功能图语言,沿用半导体逻辑框图来表达,一般一个运算框表示一个功能左边画输入、右边画输出。

4 STEP7程序的使用

4.1 创建一个项目结构,项目就象一个文件夹,所有数据都以分层的结构存在于其中,任何时候你都可以使用。在创建一个项目之后,所有其他任务都在这个项目下执行。

4.2 组态一个站,组态一个站就是指定你要使用的可编程控制器,例如S7300、S7400等。

4.3 组态硬件,组态硬件就是在组态表中指定你的控制方案所要使用的模板以及在用户程序中以什么样的地址来访问这些模板,地址一般不用修改由程序自动生成。模板的特性也可以用参数进行赋值。

4.4 组态网络和通讯连接,通讯的基础是预先组态网络,也就是要创建一个满足你的控制方案的子网,设置网络特性、设置网络连接特性以及任何联网的站所需要的连接。网络地址也是程序自动生成如果没有更改经验一定不要修改。

4.5 定义符号,可以在符号表中定义局部或共享符号,在你的用户程序中用这些更具描述性的符号名替代绝对地址。符号的命名一般用字母编写不超过8个字节,最好不要使用很长的汉字进行描述,否则对程序的执行有很大的影响。

4.6 创建程序,用梯形图编程语言创建一个与模板相连结或与模板无关的程序并存储。创建程序是我们控制工程的重要工作之一,一般可以采用线形编程(基于一个块内,OB1)、分布编程(编写功能块FB,OB1组织调用)、结构化编程(编写通用块)。我们最常采用的是结构化编程和分布编程配合使用,很少采用线形编程。

4.7 下载程序到可编程控制器,完成所有的组态、参数赋值和编程任务之后,可以下载整个用户程序到可编程控制器。在下载程序时可编程控制器必须在允许下载的工作模式下(STOP或RUN-P),

RUN-P模式表示,这个程序将一次下载一个块,如果重写一个旧的CPU程序就可能出现冲突,所以一般在下载前将CPU切换到STOP模式。

5 WINCC程序的使用

5.1 简介,WINCC是在生产和过程自动化中解决可视化和控制任务的工业技术中性系统。具有控制自动化过程的强大功能,是基于个人计算机的操作监视系统,它很容易结合标准的和用户的程序建立人机界面精确的满足生产实际要求。WINCC有两个版本RC版(具有组态和开发环境)、RT版(只有运行环境),我们一般使用的是RC版。

5.2 WINCC简单使用步骤

5.2.1 变量管理,首先确定通讯方式安装驱动程序,然后定义内部变量和外部变量,外部变量是受你买的WINCC软件授权限制的最大授权64K字节,内部变量没有限制。

5.2.2 画面生成,进入图形编辑器,图形编辑器是一种用于创建过程画面的面向矢量的作图程序。也可以使用包含在对象和样式库中的众多的图形对象来创建复杂的过程画面。可以通过动作编程将动态添加到单个图形对象上。

5.2.3 报警记录设置,报警记录提供了显示和操作选项来获取和归档结果。可以任意地选择消息块、消息级别、消息类型、消息显示以及报表。为了在运行中显示消息,可以使用包含在图形编辑器中的对象库中的报警控件。

5.2.4 变量记录,变量记录是用来从运行过程中采集数据并准备将它们显示和归档。

5.2.5 报表组态,报表组态是通过报表编辑器来实现的。是为消息、操作、归档内容和当前或已归档的数据定时器或事件控制文档的集成的报表系统,可以自由选择用户报表的形式。

5.2.6 全局脚本的应用,全局脚本就是C语言函数和动作的通称,根据不同的类型脚本被用于给对象组态动作并通过系统内部C语言编译器来处理。全局脚本动作用于过程执行的运行中。一个触发可以开始这些动作的执行。

5.2.7 用户管理器设置,用户管理器用于分配和控制用户的单个组态和运行系统编辑器的访问权限。每建立一个用户,就设置了WINCC功能的访问权利并独立的分配给此用户。至多可分配999个不同的授权。

5.2.8 交叉表索引,交叉索引用于为对象寻找和显示所有使用处,例如变量、画面和函数等。使用“链接”功能可以改变变量名称而不会导致组态不一致。

参考文献
[1] 林小峰.可编程控制器原理及应用.北京:高等教育出版社,1994
[2] 田瑞庭.可编程控制器应用技术.北京:机械工业出版社,1994
[3] 张万忠.可编程控制器应用技术.北京:化学工业出版社,2001.12
[4] 于庆广.可编程控制器原理及系统设计.北京:清华大学出版社.2004

PLC,俗称“电力线上网”,英文全名为Power Line Communication,主要是指利用电力线传输数据和话音信号的一种通信方式
1、主要特点

① 结构灵活,不受环境的限制,有电即可组建网络,同时可以灵活扩展接入端口数量,使资源保持较高的利用率,在移动性方面可与WLAN媲美。

② 传输质量高、速度快、带宽稳定,可以很平顺的在线观赏DVD影片,它所提供的14Mbps带宽可以为很多应用平台提供保证。最新的电力线标准HomePlug AV传输速度已经达到了200Mbps;为了确保QoS,HomePlug AV采用了时分多路访问(TDMA)与带有冲突检测机能的载体侦听多路访问(CSMA)协议,两者结合,能够很好地传输流媒体。

③ 范围广,无所不在的电力线网络也是这种技术的优势。虽然无线网络可以做到不破墙,但对于高层建筑来说,其必需布设N多个AP才能满足需求,而且同样不能避面信号盲区的存在。而电力线是最基础的网络,它的规模之大,是其他任何网络无法比拟的。由此,运营商就可以轻松地把这种网络接入服务渗透到每一处有电力线的地方。这一技术一旦全面进入商业化阶段,将给互联网普及带来极大的发展空间。终端用户只需要插上电力猫,就可以实现因特网接入,电视频道接收节目,打电话或者是可视电话。

④ 低成本。充分利用现有的低压配电网络基础设施,无需任何布线,节约了资源。无需挖沟和穿墙打洞,避免了对建筑物、公用设施、家庭装潢的破坏,同时也节省了人力。相对传统的组网技术,PLC成本更低,工期短,可扩展性和可管理性更强。目前国内已开通电力宽带上网的地方,其包月使用费用一般为50-80元/月左右,这样的价格和很多地方的ADSL包月相持平。

⑤ 适用面广。PLC作为利用电力线组网的一种接入技术,提供宽带网络“最后一公里”的解决方案,广泛适用于居民小区,酒店,办公区,监控安防等领域。它是利用电力线作为通信载体,使得PLC具有极大的便捷性,只要在房间任何有电源插座的地方,不用拨号,就立即可享受4.5~45Mbps的高速网络接入,来浏览网页、拨打电话,和观看在线电影,从而实现集数据、语音、视频,以及电力于一体的“四网合一”。

PLC 还有一种说法是:产品生命周期(proct life cycle)观念,简称PLC,是把一个产品的销售历史比作象人的生命周期一样,要经历出生、成长、成熟、老化、死亡等阶段。就产品而言,也就是要经历一个开发、引进、成长、成熟、衰退的阶段。
1、产品开发期:从开发产品的设想到产品制造成功的时期。此期间该产品销售额为零,公司投资不断增加。
2、引进期:新产品新上市,销售缓慢。由于引进产品的费用太高,初期通常利润偏低或为负数,但此时没有或只有极少的竞争者。
3、成长期:产品经过一段时间已有相当知名度,销售快速增长,利润也显着增加。但由于市场及利润成长较快,容易吸引更多的竞争者。
4、成熟期:此时市场成长趋势减缓或饱和,产品已被大多数潜在购买者所接受,利润在达到顶点后逐渐走下坡路。此时市场竞争激烈,公司为保持产品地位需投入大量的营销费用。
5、衰退期:这期间产品销售量显着衰退,利润也大幅度滑落。优胜劣汰,市场竞争者也越来越少。

‘贰’ 有关于VB对内存读写的操作,那位帮帮忙

晕,眼都花了~~给你篇文章看看把,VB用指针操作内存,就俩API

真没想到VB也可以这样用之指针技术

想当年东方不败,黑木崖密室一战,仅凭一根绣花针独战四大高手,神出鬼没,堪称天下武林第一高手。若想成为VB里的东方不败,熟习VB《葵花宝典》,掌握VB指针技术,乃是不二的法门。

欲练神功,引刀……,其实掌握VB指针技术,并不需要那么痛苦。因为说穿了,也就那么几招,再勤加练习,终可至神出鬼没之境。废话少说,让我们先从指针的定义说起。

一、指针是什么?

不需要去找什么标准的定义,它就是一个32位整数,在C语言和在VB里都可以用Long类型来表示。在32位Windows平台下它和普通的32位长整型数没有什么不同,只不过它的值是一个内存地址,正是因为这个整数象针一样指向一个内存地址,所以就有了指针的概念。

有统计表明,很大一部分程序缺陷和内存的错误访问有关。正是因为指针直接和内存打交道,所以指针一直以来被看成一个危险的东西。以至于不少语言,如着名的JAVA,都不提供对指针操作的支持,所有的内存访问方面的处理都由编译器来完成。而象C和C++,指针的使用则是基本功,指针给了程序员极大的自由去随心所欲地处理内存访问,很多非常巧妙的东西都要依靠指针技术来完成。

关于一门高级的程序设计语言是不是应该取消指针操作,关于没有指针操作算不算一门语言的优点,我在这里不讨论,因为互联网上关于这方面的没有结果的讨论,已经造成了占用几个GB的资源。无论最终你是不是要下定决心修习指针技术《葵花宝典》,了解这门功夫总是有益处的。

注意:在VB里,官方是不鼓励使用什么指针的,本文所讲的任何东西你都别指望取得官方的技术支持,一切都要靠我们自己的努力,一切都更刺激!

让我们开始神奇的VB指针探险吧!

二、来看看指针能做什么?有什么用?

先来看两个程序,程序的功能都是交换两个字串:

【程序一】:

'标准的做法SwapStr
Sub SwapStr(sA As String, sB As String)
Dim sTmp As String
sTmp = sA: sA = sB: sB = sTmp
End Sub

【程序二】:

'用指针的做法SwapPtr
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long)

Sub SwapPtr(sA As String, sB As String)
Dim lTmp As Long
CopyMemory lTmp, ByVal VarPtr(sA), 4
CopyMemory ByVal VarPtr(sA), ByVal VarPtr(sB), 4
CopyMemory ByVal VarPtr(sB), lTmp, 4
End Sub

你是不是以为第一个程序要快,因为它看着简单而且不用调用API(调用API需要额外的处理,VB文档明确指出大量调用API将降低程序性能)。但事实上,在VB集成环境中运行,程序二要比程序一快四分之一;而编译成本机代码或p-code,程序二基本上要比程序一快一倍。下面是两个函数在编译成本机代码后,运行不同次数所花时间的比较:

运行100000次,SwapStr需要170毫秒,SwapPtr需要90毫秒。

运行200000次,SwapStr需要340毫秒,SwapPtr需要170毫秒。

运行2000000次,SwapStr需要3300毫秒,SwapPtr需要1500毫秒。

的确,调用API是需要额外指令来处理,但是由于使用了指针技术,它没有进行临时字串的分配和拷贝,因此速度提高了不少。

怎么样,想不到吧!C/C++程序员那么依赖指针,无非也是因为使用指针往往能更直接的去处理问题的根源,更有驾驭一切的快感。他们不是不知道使用指针的危险,他们不是不愿意开卫星定位无级变速的汽车,只是骑摩托更有快感,而有些地方只有摩托才走得过去。
和在C里类似,在VB里我们使用指针也不过三个理由:

一是效率,这是一种态度一种追求,在VB里也一样;

二是不能不用,因为操作系统是C写的,它时刻都在提醒我们它需要指针;

三是突破限制,VB想照料我们的一切,VB给了我们很强的类型检查,VB象我们老妈一样,对我们关心到有时我们会受不了,想偶尔不听妈妈的话吗?你需要指针!

但由于缺少官方的技术支持,在VB里,指针变得很神秘。因此在C里一些基本的技术,在VB里就变得比较困难。本文的目的就是要提供给大家一种简单的方法,来将C处理指针的技术拿到VB里来,并告诉你什么是可行的,什么可行但必须要小心的,什么是可能但不可行的,什么是根本就不可能的。
三、 程咬金的三板斧

是的,程序二基本上就已经让我们看到VB指针技术的模样了。总结一下,在VB里用指针技术我们需要掌握三样东西:CopyMemory,VarPtr/StrPtr/ObjPtr, AdressOf. 三把斧头,程咬金的三板斧,在VB里Hack的工具。

1、CopyMemory

关于CopyMemory和Bruce McKinney大师的传奇,MSDN的Knowledge Base中就有文章介绍,你可以搜索"ID: Q129947"的文章。正是这位大师给32位的VB带来了这个可以移动内存的API,也正是有了这个API,我们才能利用指针完成我们原来想都不敢想的一些工作,感谢Bruce McKinney为我们带来了VB的指针革命。

如CopyMemory的声明,它是定义在Kernel32.dll中的RtlMoveMemory这个API,32位C函数库中的memcpy就是这个API的包装,如MSDN文档中所言,它的功能是将从Source指针所指处开始的长度为Length的内存拷贝到Destination所指的内存处。它不会管我们的程序有没有读写该内存所应有的权限,一但它想读写被系统所保护的内存时,我们就会得到着名的Access Violation Fault(内存越权访问错误),甚至会引起更着名的general protection (GP) fault(通用保护错误) 。所以,在进行本系列文章里的实验时,请注意随时保存你的程序文件,在VB集成环境中将"工具"->"选项"中的"环境"选项卡里的"启动程序时"设为"保存改变",并记住在"立即"窗口中执行危险代码之前一定要保存我们的工作成果。

2、VatPtr/StrPtr/ObjPtr

它们是VB提供给我们的好宝贝,它们是VBA函数库中的隐藏函数。为什么要隐藏?因为VB开发小组,不鼓励我们用指针嘛。

实际上这三个函数在VB运行时库MSVBVM60.DLL(或MSVBVM50.DLL)中是同一个函数VarPtr(可参见我在本系列第一篇文章里介绍的方法)。

其库型库定义如下:

[entry("VarPtr"), hidden]
long _stdcall VarPtr([in] void* Ptr);
[entry("VarPtr"), hidden]
long _stdcall StrPtr([in] BSTR Ptr);
[entry("VarPtr"), hidden]
long _stdcall ObjPtr([in] IUnknown* Ptr);

即然它们是VB运行时库中的同一个函数,我们也可以在VB里用API方式重新声明这几个函数,如下:

Private Declare Function ObjPtr Lib "MSVBVM60" Alias "VarPtr" (var As Object) As Long
Private Declare Function VarPtr Lib "MSVBVM60" (var As Any) As Long

(没有StrPtr,是因为VB对字符串处理方式有点不同,这方面的问题太多,我将在另一篇文章中详谈。顺便提一下,听说VB.NET里没有这几个函数,但只要还能调用API,我们就可以试试上面的几个声明,这样在VB.NET里我们一样可以进行指针操作。但是请注意,如果通过API调用来使用VarPtr,整个程序二SwapPtr将比原来使用内置VarPtr函数时慢6倍。)

如果你喜欢刨根问底,那么下面就是VarPtr函数在C和汇编语言里的样子:

在C里样子是这样的:

long VarPtr(void* pv){
return (long)pv;
}

所对就的汇编代码就两行:

mov eax,dword ptr [esp+4]
ret 4 '弹出栈里参数的值并返回。

之所以让大家了解VarPtr的具体实现,是想告诉大家它的开销并不大,因为它们不过两条指令,即使加上参数赋值、压栈和调用指令,整个获取指针的过程也就六条指令。当然,同样的功能在C语言里,由于语言的直接支持,仅需要一条指令即可。但在VB里,它已经算是最快的函数了,所以我们完全不用担心使用VarPtr会让我们失去效率!速度是使用指针技术的根本要求。

一句话,VarPtr返回的是变量所在处的内存地址,也可以说返回了指向变量内存位置的指针,它是我们在VB里处理指针最重要的武器之一。

3、ByVal和ByRef

ByVal传递的参数值,而ByRef传递的参数的地址。在这里,我们不用去区别传指针/传地址/传引用的不同,在VB里,它们根本就是一个东西的三种不同说法,即使VB的文档里也有地方在混用这些术语(但在C++里的确要区分指针和引用)

初次接触上面的程序二SwapPtr的朋友,一定要搞清在里面的CopyMemory调用中,在什么地方要加ByVal,什么地方不加(不加ByVal就是使用VB缺省的ByRef),准确的理解传值和传地址(指针)的区别,是在VB里正确使用指针的基础。

现在一个最简单的实验来看这个问题,如下面的程序三:

【程序三】:

'体会ByVal和ByRef
Sub TestCopyMemory()
Dim k As Long
k = 5
Note: CopyMemory ByVal VarPtr(k), 40000, 4
Debug.Print k
End Sub

上面标号Note处的语句的目的,是将k赋值为40000,等同于语句k=40000,你可以在"立即"窗口试验一下,会发现k的值的确成了40000。
实际上上面这个语句,翻译成白话,就是从保存常数40000的临时变量处拷贝4个字节到变量k所在的内存中。

现在我们来改变一个Note处的语句,若改成下面的语句:

Note2: CopyMemory ByVal VarPtr(k), ByVal 40000, 4

这句话的意思就成了,从地址40000拷贝4个字节到变量k所在的内存中。由于地址40000所在的内存我们无权访问,操作系统会给我们一个Access Violation内存越权访问错误,告诉我们"试图读取位置0x00009c40处内存时出错,该内存不能为'Read'"。

我们再改成如下的语句看看。

Note3: CopyMemory VarPtr(k), 40000, 4

这句话的意思就成了,从保存常数40000的临时变量处拷贝4个字节到到保存变量k所在内存地址值的临时变量处。这不会出出内存越权访问错误,但k的值并没有变。

我们可以把程序改改以更清楚的休现这种区别,如下面的程序四:

【程序四】:

'看看我们的东西被拷贝到哪儿去了
Sub TestCopyMemory()
Dim i As Long, k As Long
k = 5
i = VarPtr(k)
NOTE4: CopyMemory i, 40000, 4
Debug.Print k
Debug.Print i
i = VarPtr(k)
NOTE5: CopyMemory ByVal i, 40000, 4
Debug.Print k
End Sub

程序输出:

5
40000
40000

由于NOTE4处使用缺省的ByVal,传递的是i的地址(也就是指向i的指针),所以常量40000拷贝到了变量i里,因此i的值成了40000,而k的值却没有变化。但是,在NOTE4前有:i=VarPtr(k),本意是要把i本身做为一个指针来使用。这时,我们必须如NOTE5那样用ByVal来传递指针i,由于i是指向变量k的指针,所以最后常量40000被拷贝了变量k里。

希望你已经理解了这种区别,在后面问题的讨论中,我还会再谈到它。
4、AddressOf

它用来得到一个指向VB函数入口地址的指针,不过这个指针只能传递给API使用,以使得API能回调VB函数。

本文不准备详细讨论函数指针,关于它的使用请参考VB文档。

5、拿来主义

实际上,有了CopyMemory,VarPtr,AddressOf这三把斧头,我们已经可以将C里基本的指针操作拿过来了。

如下面的C程序包括了大部分基本的指针指针操作:

struct POINT{
int x; int y;
};

int Compare(void* elem1, void* elem2){}

void PtrDemo(){
//指针声明:
char c = 'X'; //声明一个char型变量
char* pc; long* pl; //声明普通指针
POINT* pPt; //声明结构指针
void* pv; //声明无类型指针
int (*pfnCastToInt)(void *, void*);//声明函数指针:
//指针赋值:
pc = &c; //将变量c的地址值赋给指针pc
pfnCompare = Compare; //函数指针赋值。
//指针取值:
c = *pc; //将指针pc所指处的内存值赋给变量c
//用指针赋值:
*pc = 'Y' //将'Y'赋给指针pc所指内存变量里。
//指针移动:
pc++; pl--;
}

这些对指针操作在VB里都有等同的东西,前面讨论ByVal和ByRef时曾说过传指针和传地址是一回事,实际上当我们在VB里用缺省的ByRef声明函数参数时,我们已经就声明了指针。

如一个C声明的函数:long Func(char* pc)

其对应的VB声明是:Function Func(pc As Byte) As Long

这时参数pc使用缺省的ByRef传地址方式来传递,这和C里用指针来传递参数是一样。

那么怎么才能象C里那样明确地声明一个指针呢?

很简单,如前所说,用一个32位长整数来表达指针就行。在VB里就是用Long型来明确地声明指针,我们不用区分是普通指针、无类型指针还是函数指针,通通都可用Long来声明。而给一个指针赋值,就是赋给它用VarPar得到的另一个变量的地址。具体见程序五。

【程序五】:同C一样,各种指针。

Type POINT
X As Integer
Y As Integer
End Type

Public Function Compare(elem1 As Long, elem2 As Long) As Long
'
End Function

Function FnPtrToLong(ByVal lngFnPtr As Long) As Long
FnPtrToLong = lngFnPtr
End Function

Sub PtrDemo()
Dim l As Long, c As Byte, ca() As Byte, Pt As POINT
Dim pl As Long, pc As Long, pv As Long, pPt As Long, pfnCompare As Long
c = AscB("X")
pl = VarPtr(l) '对应C里的long、int型指针
pc = VarPtr(c) '对应char、short型指针
pPt = VarPtr(Pt) '结构指针
pv = VarPtr(ca(0)) '字节数组指针,可对应任何类型,也就是void*
pfnCompare = FnPtrToLong(AddressOf Compare) '函数指针
CopyMemory c, ByVal pc, LenB(c) '用指针取值
CopyMemory ByVal pc, AscB("Y"), LenB(c) '用指针赋值
pc = pc + LenB(c) : pl = pl - LenB(l) '指针移动
End Sub

我们看到,由于VB不直接支持指针操作,在VB里用指针取值和用指针赋值都必须用CopyMemory这个API,而调用API的代价是比较高的,这就决定了我们在VB里使用指针不能象在C里那样自由和频繁,我们必须要考虑指针操作的代价,在后面的"指针应用"我们会再变谈这个问题。

程序五中关于函数指针的问题请参考VB文档,无类型指针void*会在下面"关于Any的问题"里说。

程序五基本上已经包括了我们能在VB里进行的所有指针操作,仅此而已。

下面有一个小测试题,如果现在你就弄懂了上面程咬金的三板斧,你就应该能做得出来。

上面提到过,VB.NET中没有VarPtr,我们可以用声明API的方式来引入MSVBVM60.DLL中的VarPtr。现在的问题如果不用VB的运行时DLL文件,你能不能自己实现一个ObjPtr。答案在下一节后给出。
四、指针使用中应注意的问题

1、关于ANY的问题

如果以一个老师的身份来说话,我会说:最好永远也不要用Any!是的,我没说错,是永远!所以我没有把它放在程咬金的三板斧里。当然,这个问题和是不是应该使用指针这个问题一样会引发一场没有结果的讨论,我告诉你的只是一个观点,因为有时我们会为了效率上的一点点提高或想偷一点点懒而去用Any,但这样做需要要承担风险。

Any不是一个真正的类型,它只是告诉VB编译器放弃对参数类型的检查,这样,理论上,我们可以将任何类型传递给API。

Any在什么地方用呢?让我们来看看,在VB文档里的是怎么说的,现在就请打开MSDN(Visual Studio 6自带的版本),翻到"Visual Basic文档"->"使用Visual Basic"->"部件工具指南"->"访问DLL和Windows API"部分,再看看"将 C 语言声明转换为 Visual Basic 声明"这一节。文档里告诉我们,只有C的声明为LPVOID和NULL时,我们才用Any。实际上如果你愿意承担风险,所有的类型你都可以用Any。当然,也可以如我所说,永远不要用Any。

为什么要这样?那为什么VB官方还要提供Any?是信我的,还是信VB官方的?有什么道理不用Any?

如前面所说,VB官方不鼓励我们使用指针。因为VB所标榜的优点之一,就是没有危险的指针操作,所以的内存访问都是受VB运行时库控制的。在这一点上,JAVA语言也有着同样的标榜。但是,同JAVA一样,VB要避免使用指针而得到更高的安全性,就必须要克服没有指针而带来的问题。VB已经尽最大的努力来使我们远离指针的同时拥有强类型检查带来的安全性。但是操作系统是C写的,里面到处都需要指针,有些指针是没有类型的,就是C程序员常说的可怕的void*无类型指针。它没有类型,因此它可以表示所有类型。如CopyMemory所对应的是C语言的memcpy,它的声明如下:

void *memcpy( void *dest, const void *src, size_t count );

因memcpy前两个参数用的是void*,因此任何类型的参数都可以传递给他。

一个用C的程序员,应该知道在C函数库里这样的void*并不少见,也应该知道它有多危险。无论传递什么类型的变量指针给上面memcpy的void*,C编译器都不会报错或给任何警告。

在VB里大多数时候,我们使用Any就是为了使用void*,和在C里一样,VB也不对Any进行类型检查,我们也可以传递任何类型给Any,VB编译器也都不会报错或给任何警告。

但程序运行时会不会出错,就要看使用它时是不是小心了。正因为在C里很多错误是和void*相关的,所以,C++鼓励我们使用satic_cast<void*>来明确指出这种不安全的类型的转换,已利于发现错误。

说了这么多C/C++,其实我是想告诉所有VB的程序员,在使用Any时,我们必须和C/C++程序员使用void*一样要高度小心。

VB里没有satic_cast这种东西,但我们可以在传递指针时明确的使用long类型,并且用VarPtr来取得参数的指针,这样至少已经明确地指出我们在使用危险的指针。如程序二经过这样的处理就成了下面的程序:

【程序五】:

'使用更安全的CopyMemory,明确的使用指针!
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Sub SwapStrPtr2(sA As String, sB As String)
Dim lTmp As Long
Dim pTmp As Long, psA As Long, psB As Long
pTmp = VarPtr(lTmp): psA = VarPtr(sA): psB = VarPtr(sB)
CopyMemory pTmp, psA, 4
CopyMemory psA, psB, 4
CopyMemory psB, pTmp, 4
End Sub

注意,上面CopyMemory的声明,用的是ByVal和long,要求传递的是32位的地址值,当我们将一个别的类型传递给这个API时,编译器会报错,比如现在我们用下面的语句:

【程序六】:

'有点象【程序四】,但将常量40000换成了值为1的变量.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, Length As Long)
Sub TestCopyMemory()
Dim i As Long,k As Long, z As Interger
k = 5 : z = 1
i = VarPtr(k)
'下面的语句会引起类型不符的编译错误,这是好事!
'CopyMemory i, z, 4
'应该用下面的
CopyMemory i, ByVal VarPtr(z), 2
Debug.Print k
End Sub

编译会出错!是好事!这总比运行时不知道错在哪儿好!

象程序四那样使用Any类型来声明CopyMemory的参数,VB虽然不会报错,但运行时结果却是错的。不信,你试试将程序四中的40000改为1,结果i的值不是我们想要的1,而是327681。为什么在程序四中,常量为1时结果会出错,而常量为40000时结果就不错?

原因是VB对函数参数中的常量按Variant的方式处理。是1时,由于1小于Integer型的最大值32767,VB会生成一个存储值1的Integer型的临时变量,也就是说,当我们想将1用CopyMemroy拷贝到Long型的变量i时,这个常量1是实际上是Integer型临时变量!VB里Integer类型只有两个字节,而我们实际上拷贝了四个字节。知道有多危险了吧!没有出内存保护错误那只是我们的幸运!

如果一定要解释一下为什么i最后变成了327681,这是因为我们将k的低16位的值5也拷贝到了i值的高16位中去了,因此有5*65536+1=327681。详谈这个问题涉及到VB局部变量声明顺序,CopyMemory参数的压栈顺序,long型的低位在前高位在后等问题。如果你对这些问题感兴趣,可以用本系列第一篇文章所提供的方法(DebugBreak这个API和VC调试器)来跟踪一下,可以加深你对VB内部处理方式的认识,由于这和本文讨论的问题无关,所以就不详谈了。到这里,大家应该明白,程序三和程序四实际上有错误!!!我在上面用常量40000而不用1,不是为了在文章中凑字数,而是因为40000这个常量大于32767,会被VB解释成我们需要的Long型的临时变量,只有这样程序三和程序四才能正常工作。对不起,我这样有意的隐藏错误只是想加深你对Any危害的认识。

总之,我们要认识到,编译时就找到错误是非常重要的,因为你马上就知道错误的所在。所以我们应该象程序五和程序六那样明确地用long型的ByVal的指针,而不要用Any的ByRef的指针。

但用Any已经如此的流行,以至很多大师们也用它。它唯一的魅力就是不象用Long型指针那样,需要我们自己调用VarPtr来得到指针,所有处理指针的工作由VB编译器来完成。所以在参数的处理上,只用一条汇编指令:push ,而用VarPtr时,由于需要函数调用,因此要多用五条汇编指令。五条多余的汇编指令有时的确能我们冒着风险去用Any。

VB开发小组提供Any,就是想用ByRef xxx As Any来表达void* xxx。我们也完全可以使用VarPtr和Long型的指针来处理。我想,VB开发小组也曾犹豫过是公布VarPtr,还是提供Any,最后他们决定还是提供Any,而继续隐瞒VarPtr。的确,这是个两难的决定。但是经过我上面的分析,我们应该知道,这个决定并不符合VB所追求的"更安全"的初衷。因为它可能会隐藏类型不符的错误,调试和找到这种运行时才产生的错误将花贵更多的时间和精力。

所以我有了"最好永远不要用Any"这个"惊人"的结论。

不用Any的另一个好处是,简化了我们将C声明的API转换成VB声明的方式,现在它变成了一句话:除了VB内置的可以进行类型检查的类型外,所以其它的类型我们都应该声明成Long型。

2、关于NULL的容易混淆的问题

有很多文章讲过,一定要记在心里:

VbNullChar 相当于C里的'\0',在用字节数组构造C字串时常用它来做最后1个元素。

vbNullString 这才是真正的NULL,就是0,在VB6中直接用0也可以。

只有上面的两个是API调用中会用的。还有Empty、Null是Variant,而Nothing只和类对象有关,一般API调用中都不会用到它们。

另:本文第三节曾提出一个小测验题,做出来了吗?现在公布正确答案:

【测验题答案】

Function ObjPtr(obj as Object) as long
Dim lpObj As Long
CopyMemory lpObj, Obj, 4
ObjectPtr = lpObj
End Function

五、VB指针应用

如前面所说VB里使用指针不象C里那样灵活,用指针处理数据时都需要用CopyMemory将数据在指针和VB能够处理的变量之间来回拷贝,这需要很大的额外开销。因此不是所有C里的指针操作都可以移值到VB里来,我们只应在需要的时候才在VB里使用指针。

1、动态内存分配:完全不可能、可能但不可行,VB标准

在C和C++里频繁使用指针的一个重要原因是需要使用动态内存分配,用Malloc或New来从堆栈里动态分配内存,并得到指向这个内存的指针。在VB里我们也可以自己

用API来实现动态分配内存,并且实现象C里的指针链表。

但我们不可能象C那样直接用指针来访问这样动态分配的内存,访问时我们必须用CopyMemory将数据拷贝到VB的变量内,大量的使用这种技术必然会降低效率,以至于要象C那样用指针来使用动态内存根本就没有可行性。要象C、PASCAL那样实现动态数据结构,在VB里还是应该老老实实用对象技术来实现。

本文配套代码中的LinkedList里有完全用指针实现的链表,它是使用HeapAlloc从堆栈中动态分配内存,另有一个调用FindFirstUrlCacheEntry这个API来操作IE的Cache的小程序IECache,它使用了VirtualAlloc来动态分配内存。但实际上这都不是必须的,VB已经为我们提供了标准的动态内存分配的方法,那就是:

对象、字符串和字节数组

限于篇幅,关于对象的技术这里不讲,LinkedList的源代码里有用对象实现的链表,你可以参考。

字符串可以用Space$函数来动态分配,VB的文档里就有详细的说明。

关于字节数组,这里要讲讲,它非常有用。我们可用Redim来动态改变它的大小,并将指向它第一个元素的指针传给需要指针的API,如下:

dim ab() As Byte , ret As long
'传递Null值API会返回它所需要的缓冲区的长度。
ret = SomeApiNeedsBuffer(vbNullString)
'动态分配足够大小的内存缓冲区
ReDim ab(ret) As Byte
'再次把指针

‘叁’ pid控制的C语言编程

#include<unistd.h>
#include<stdio.h>
int main(int argc,int **argv)
{
int pid=fork();
if(pid==-1)
{
printf("error");
}
else if(pid==0)
{
printf("This is the child process!\n");
}
else
{
printf("This is the parent process! child process id=%d\n",pid);
}
return 0;
}
首先为什么这段代码gcc编没兆译不了,只能用g++编译,gcc编译显示结果如下
Undefined first referenced
symbol in file
__gxx_personality_v0 /var/tmp//ccuHN8IS.o
ld: fatal: Symbol referencing errors. No output written to t5
collect2: ld returned 1 exit status
其次,g++编译桥察租后运行结果敏兆如下
This is the parent process! child process id=27406
This is the child process!

阅读全文

与pidc编译器相关的资料

热点内容
电脑服务器地址ip地址 浏览:823
对矩阵压缩是为了 浏览:910
setfacl命令 浏览:172
linux子系统中断 浏览:342
linux查看进程ps 浏览:224
知识库系统php 浏览:623
小波变换压缩图像python 浏览:151
阿里巴巴程序员怎么月入百万 浏览:173
如何使用国外服务器 浏览:188
燃灯者pdf 浏览:468
编译器用数学吗 浏览:7
图形化apk反编译工具 浏览:48
考勤表加密怎么办 浏览:735
arj压缩与解压批处理怎么写 浏览:658
php和大数据哪个好 浏览:930
未来最值得投资的加密货币 浏览:526
ascii码是编译的时候用吗 浏览:782
压缩机感应包可以通用吗 浏览:413
方舟服务器怎么发布到搜索列表 浏览:271
xml防反编译 浏览:242