PASCALF口转C口有什么要注意的,求教

为了更加合法合规运营网站我們正在对全站内容进行审核,之前的内容审核通过后才能访问

由于审核工作量巨大,完成审核还需要时间我们正在想方设法提高审核速度,由此给您带来麻烦请您谅解。

如果您访问园子时跳转到这篇博文说明当前访问的内容还在审核列表中,如果您急需访问麻烦您将对应的网址反馈给我们,我们会优先审核


· TA获得超过3.5万个赞

是两个源代码轉换程序.

时这两个程序都会被安装上去.

代码一般不用修改就直接能被

程序比较小的话可以直接使用

p2c不用加任何选项.

如果要转换的程序比较龐大,

包含很多文件的话可能要用到一些命令行选项.

要求被转换的程序的扩展名为

源代码的文件名都和原来的文件名相同,

你对这个回答的评價是

下载百度知道APP,抢鲜体验

使用百度知道APP立即抢鲜体验。你的手机镜头里或许有别人想知道的答案

  简而言之回调函数就是一個通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数当这个指针被用为调用它所指向的函数时,我们僦说这是回调函数

   为什么要使用回调函数?  因为可以把调用者与被调用者分开调用者不关心谁是被调用者,所有它需知道的只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。

  如果想知道回调函数在实际中有什么作用先假设囿这样一种情况,我们要编写一个库它提供了某些排序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等但为使库更加通用,不想在函数中嵌入排序逻辑而让使用者来实现相应的逻辑;或者,想让库可用于多种数据类型(int、float、string)此时,该怎么办呢可以使用函數指针,并进行回调

  回调可用于通知机制,例如有时要在程序中设置一个计时器,每到一定时间程序会得到相应的通知,但通知机制的实现者对我们的程序一无所知而此时,就需有一个特定原型的函数指针用这个指针来进行回调,来通知我们的程序事件已经發生实际上,SetTimer() API使用了一个回调函数来通知计时器而且,万一没有提供回调函数它还会把一个消息发往程序的消息队列。

  另一个使用回调机制的API函数是EnumWindow()它枚举屏幕上所有的顶层窗口,为每个窗口调用一个程序提供的函数并传递窗口的处理程序。如果被调用者返囙一个值就继续进行迭代,否则退出。EnumWindow()并不关心被调用者在何处也不关心被调用者用它传递的处理程序做了什么,它只关心返回值因为基于返回值,它将继续执行或退出

  不管怎么说,回调函数是继续自C语言的因而,在C++中应只在与C代码建立接口,或与已有嘚回调接口打交道时才使用回调函数。除了上述情况在C++中应使用虚拟方法或函数符(functor),而不是回调函数

byte*),它就是回调函数的类型另外,它也导出了两个方法:Bubblesort()和Quicksort()这两个方法原型相同,但实现了不同的排序算法


  这两个函数接受以下参数:

  ·byte * array:指向元素數组的指针(任意类型)。

  ·int size:数组中元素的个数

  ·int elem_size:数组中一个元素的大小,以字节为单位

  这两个函数的会对数组进荇某种排序,但每次都需决定两个元素哪个排在前面而函数中有一个回调函数,其地址是作为一个参数传递进来的对编写者来说,不必介意函数在何处实现或它怎样被实现的,所需在意的只是两个用于比较的元素的地址并返回以下的某个值(库的编写者和使用者都必须遵守这个约定):

  ·-1:如果第一个元素较小,那它在已排序好的数组中应该排在第二个元素前面。

  ·0:如果两个元素相等那么它们的相对位置并不重要,在已排序好的数组中谁在前面都无所谓。

  ·1:如果第一个元素较大那在已排序好的数组中,它應该排第二个元素后面

  基于以上约定,函数Bubblesort()的实现如下Quicksort()就稍微复杂一点:


  注意:因为实现中使用了memcpy(),所以函数在使用的数据類型方面会有所局限。

  对使用者来说必须有一个回调函数,其地址要传递给Bubblesort()函数下面有二个简单的示例,一个比较两个整数洏另一个比较两个字符串:


  下面另有一个程序,用于测试以上所有的代码它传递了一个有5个元素的数组给Bubblesort()和Quicksort(),同时还传递了一个指姠回调函数的指针


  如果想进行降序排序(大元素在先),就只需修改回调函数的代码或使用另一个回调函数,这样编程起来灵活性就比较大了

调用约定  上面的代码中,可在函数原型中找到__stdcall因为它以双下划线打头,所以它是一个特定于编译器的扩展说到底吔就是微软的实现。任何支持开发基于Win32的程序都必须支持这个扩展或其等价物以__stdcall标识的函数使用了标准调用约定,为什么叫标准约定呢因为所有的Win32 API(除了个别接受可变参数的除外)都使用它。标准调用约定的函数在它们返回到调用者之前都会从堆栈中移除掉参数,这吔是Pascal的标准约定但在C/C++中,调用约定是调用者负责清理堆栈而不是被调用函数;为强制函数使用C/C++调用约定,可使用__cdecl另外,可变参数函數也使用C/C++调用约定

  Windows操作系统采用了标准调用约定(Pascal约定),因为其可减小代码的体积这点对早期的Windows来说非常重要,因为那时它运荇在只有640KB内存的电脑上


作为回调函数的C++方法

  因为平时很可能会使用到C++编写代码,也许会想到把回调函数写成类中的一个方法但先來看看以下的代码:

  如果使用微软的编译器,将会得到下面这个编译错误:
  这是因为非静态成员函数有一个额外的参数:this指针這将迫使你在成员函数前面加上static。当然还有几种方法可以解决这个问题,但限于篇幅就不再论述了 .

回调到底层次的看法就是:

让函数去"洎主"调用函数,而不是由你决定.

短歌说:它算是一种动态绑定的技术,


主要用于对某一事件的正确响应.

3.声明函数指针并回调

程序员常常需要实现囙调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调注意这里针对的是普通的函数,不包括完全依赖于不同语法和語义规则的类成员函数(类成员指针将在另文中讨论)

        回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者從而实现调用。要实现回调必须首先定义函数指针。尽管定义的语法有点不可思议但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似请看下面的例子:

上面的语句声明了一个函数,没有输入参数并返回void那么函数指针的声明方法如下:

        讓我们来分析一下,左边圆括弧中的星号是函数指针声明的关键另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例Φ参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指針的大小:

// 获得函数指针的大小

// 为函数指针声明类型定义

pfv是一个函数指针,它指向的函数没有输入参数返回类行为void。使用这个类型定义洺可以隐藏复杂的函数指针语法

指针变量应该有一个变量名:

        p是指向某函数的指针,该函数无输入参数返回值的类型为void。左边圆括弧裏星号后的就是指针变量名有了指针变量便可以赋值,值的内容是署名匹配的函数名和返回类型例如:

p的赋值可以不同,但一定要是函数的地址并且署名和返回类型相同。

传递回调函数的地址给调用者

        如果赋了不同的值给p(不同函数地址)那么调用者将调用不同地址的函数。赋值可以发生在运行时这样使你能实现动态绑定。

Builder也支持_fastcall调用规范调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右)堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)

        将调用规范看成是函数类型嘚一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:

// 被调用函数是以int为参数以int为返回值

// 调用函数以函数指针為参数

// 在p中企图存储被调用函数地址的非法操作

        指针p和callee()的类型不兼容,因为它们有不同的调用规范因此不能将被调用者的地址赋值给指針p,尽管两者有相同的返回值和参数列

4函数指针和回调函数

你不会每天都使用函数指针,但是它们确有用武之地,两个最常见的用途昰把函数指针作为参数传递给另一个函数以及用于转换表(jump table)

        第 2 个声明创建了函数指针 pf ,并把它初始化为指向函数 f 函数指针的初始化吔可以通过一条赋值语句来完成。 在函数指针的初始化之前具有 f 的原型是很重要的否则编译器就无法检查 f 的类型是否与 pf

        初始化表达式中嘚 & 操作符是可选的,因为函数名被使用时总是由编译器把它转换为函数指针 & 操作符只是显式地说明了编译器隐式执行的任务。

        第 1 条语句簡单地使用名字调用函数 f 但它的执行过程可能和你想象的不太一样。 函数名 f 首先被转换为一个函数指针该指针指定函数在内存中的位置。然后 函数调用操作符调用该函数,执行开始于这个地址的代码
        第 2 条语句对 pf 执行间接访问操作,它把函数指针转换为一个函数名這个转换并不是真正需要的,因为编译器在执行函数调用操作符之前又会把它转换回去不过,这条语句的效果和第1条是完全一样的

        这個函数看上去相当简单,但它只适用于值为整数的链表如果你需要在一个字符串链表中查找,你不得不另外编写一个函数这个函数和仩面那个函数的绝大部分代码相同,只是第 2 个参数的类型以及节点值的比较方法不同

        一种更为通用的方法是使查找函数与类型无关,这樣它就能用于任何类型的值的链表我们必须对函数的两个方面进行修改,使它与类型无关

        首先,我们必须改变比较的执行方式这样函数就可以对任何类型的值进行比较。这个目标听上去好像不可能如果你编写语句用于比较整型值,它怎么还可能用于其它类型如字符串的比较呢 解决方案就是使用函数指针。调用者编写一个比较函数用于比较两个值,然后把一个指向此函数的指针作为参数传递给查找函数而后查找函数来执行比较。使用这种方法任何类型的值都可以进行比较。

形参用于接收这个参数。然后指向这个值的指针便傳递给比较函数(这个修改使字符串和数组对象也可以被使用。字符串和数组无法作为参数传递给函数但指向它们的指针却可以。)

function)因为用户把一个函数指针作为参数传递其它函数,后者将”回调“用户的函数任何时候,如果你所编写的函数必须能够在不同的时刻执行不同类型的工作或者执行只能由函数调用者定义的工作你都可以使用这个技巧。
       在使用比较函数的指针之前它们必须被强制转換为正确的类型。因为强制类型转换能够躲开一般的类型检查所以你在使用时必须格外小心,确保函数参数类型是正确的

在这个例子裏,回调函数比较两个值查找函数向比较函数传递两个指向需要进行比较的值的指针,并检查比较函数的返回值例如:零表示相等的徝,现在查找函数就与类型无关因为它本身并不执行实际的比较。确实调用者必须编写必需的比较函数,但这样做是很容易的因为調用者知道链表中所包含的值的类型。如果使用几个分别包含不同类型值的链表为每种类型编写一个比较函数就允许单个查找函数作用於所有类型的链表。

        程序段01 是类型无关的查找函数的一种实现方法 注意函数的第 3 个参数是一个函数指针。这个参数用一个完整的原型进荇声明同时注意虽然函数绝不会修改参数 node 所指向的任何节点,但 node 并未被声明为 const 如果 node 被声明为 const,函数将不得不返回一个const结果这将限制調用程序,它便无法修改查找函数所找到的节点

        为什么要调用函数来执行这些操作呢? 把具体操作和选择操作的代码分开是一种良好的設计方法更为复杂的操作将肯定以独立的函数来实现,因为它们的长度可能很长但即使是简单的操作也可能具有副作用,例如保存一個常量值用于以后的操作

        为了使用 switch 语句,表示操作符的代码必须是整数如果它们是从零开始连续的整数,我们可以使用转换表来实现楿同的任务转换表就是一个函数指针数组。

        创建一个转换表需要两个步骤首先,声明并初始化一个函数指针数组唯一需要留心之处僦是确保这些函数的原型出现在这个数组的声明之前。

我要回帖

更多关于 A转C 的文章

 

随机推荐