|
|
用户名:badcup 笔名:badcup 地区: 北京 行业:其他 |
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
欢迎访问badcup的博客
透析回调函数
“先泛后精,先浅后深”的道理可是知易行难,所以常常会给技术上的小细节纠缠着,搞得晕晕乎,其中“回调函数”就是其中之一了,虽然回用,但是老是不明白其中的含义,众多的书本也说得隐晦不清。直到不久前看到一篇文章才总算比较清晰了解。
概括起来,回调机制包括两部分:服务执行者和服务方式制定者。
1. 服务执行者先制定服务规范;
2.服务方式制定者然后按照规范制定服务方式;
3.然后执行者按照这个方式提供服务。
回调函数的方式是把函数指针的作为参数传递进,所以规范就是约定函数的参数类型,个数。
这篇文章如下:
调用(calling)机制从汇编时代起已经大量使用:准备一段现成的代码,调用者可以随时跳转至此段代码的起始地址,执行完后再返回跳转时的后续地址。 CPU为此准备了现成的调用指令,调用时可以压栈保护现场,调用结束后从堆栈中弹出现场地址,以便自动返回。借堆栈保护现场真是一项绝妙的发明,它使调用者和被调者可以互不相识,于是才有了后来的函数和构件,使吾辈编程者如此轻松愉快。若评选对人类影响最大之发明,在火与车轮之后,笔者当推压栈调用。
话虽这样说,此调用机制并非完美。回调函数就是一例。函数之类本是为调用者准备的美餐,其烹制者应对食客了如指掌,但实情并非如此。例如,写一个快速排序函数供他人调用,其中必包含比较大小。麻烦来了:此时并不知要比较的是何类数据--整数、浮点数、字符串?于是只好为每类数据制作一个不同的排序函数。更通行的办法是在函数参数中列一个回调函数地址,并通知调用者:君需自己准备一个比较函数,其中包含两个指针类参数,函数要比较此二指针所指数据之大小,并由函数返回值说明比较结果。排序函数借此调用者提供的函数来比较大小,借指针传递参数,可以全然不管所比较的数据类型。被调用者回头调用调用者的函数(够咬嘴的),故称其为回调(callback)。
回调函数使程序结构乱了许多。Windows API 函数集中有不少回调函数,尽管有详尽说明,仍使初学者一头雾水。恐怕这也是无奈之举。无论何种事物,能以树形结构单向描述毕竟让人舒服些。如果某家族中孙辈又是某祖辈的祖辈,恐怕无人能理清其中的头绪。但数据处理之复杂往往需要构成网状结构,非简单的客户/服务器关系能穷尽。
Windows 系统还包含着另一种更为广泛的回调机制,即消息机制。消息本是 Windows 的基本控制手段,乍看与函数调用无关,其实是一种变相的函数调用。发送消息的目的是通知收方运行一段预先准备好的代码,相当于调用一个函数。消息所附带的 WParam 和 LParam 相当于函数的参数,只不过比普通参数更通用一些。应用程序可以主动发送消息,更多情况下是坐等 Windows 发送消息。一旦消息进入所属消息队列,便检感兴趣的那些,跳转去执行相应的消息处理代码。操作系统本是为应用程序服务,由应用程序来调用。而应用程序一旦启动,却要反过来等待操作系统的调用。这分明也是一种回调,或者说是一种广义回调。其实,应用程序之间也可以形成这种回调。假如进程 B 收到进程 A 发来的消息,启动了一段代码,其中又向进程 A 发送消息,这就形成了回调。这种回调比较隐蔽,弄不好会搞成递归调用,若缺少终止条件,将会循环不已,直至把程序搞垮。若是故意编写成此递归调用,并设好终止条件,倒是很有意思。但这种程序结构太隐蔽,除非十分必要,还是不用为好。
利用消息也可以构成狭义回调。上面所举排序函数一例,可以把回调函数地址换成窗口handle。如此,当需要比较数据大小时,不是去调用回调函数,而是借 API 函数 SendMessage 向指定窗口发送消息。收到消息方负责比较数据大小,把比较结果通过消息本身的返回值传给消息发送方。所实现的功能与回调函数并无不同。当然,此例中改为消息纯属画蛇添脚,反倒把程序搞得很慢。但其他情况下并非总是如此,特别是需要异步调用时,发送消息是一种不错的选择。假如回调函数中包含文件处理之类的低速处理,调用方等不得,需要把同步调用改为异步调用,去启动一个单独的线程,然后马上执行后续代码,其余的事让线程慢慢去做。一个替代办法是借 API 函数 PostMessage发送一个异步消息,然后立即执行后续代码。这要比自己搞个线程省事许多,而且更安全。
如今我们是活在一个 object 时代。只要与编程有关,无论何事都离不开 object。但 object 并未消除回调,反而把它发扬光大,弄得到处都是,只不过大都以事件(event)的身份出现,镶嵌在某个结构之中,显得更正统,更容易被人接受。应用程序要使用某个构件,总要先弄清构件的属性、方法和事件,然后给构件属性赋值,在适当的时候调用适当的构件方法,还要给事件编写处理例程,以备构件代码来调用。何谓事件?它不过是一个指向事件例程的地址,与回调函数地址没什么区别。
不过,此种回调方式比传统回调函数要高明许多。首先,它把让人不太舒服的回调函数变成一种自然而然的处理例程,使编程者顿觉气顺。再者,地址是一个危险的东西,用好了可使程序加速,用不好处处是陷阱,程序随时都会崩溃。现代编程方式总是想法把地址隐藏起来(隐藏比较彻底的如 VB 和 Java),其代价是降低了程序效率。事件例程使编程者无需直接操作地址,但并不会使程序减速。更妙的是,此一改变,本是有损程序结构之奇技怪巧变成一种崭新设计理念,不仅免去被人抨击,而且逼得吾等凡人净手更衣,细细研读,仰慕至今。只是偶然静心思虑,发觉不过一瓶旧酒而已,故引得此番议论,让诸君见笑了。 事件驱动程序设计是围绕着消息基础形成的,发生一个事件,伴随着一大堆的消息。
我理解“回调机制”是window 在执行某个API函数的过程中,调用指定的一个函数。我们可以模拟一下:
假设 ms 提供一个函数叫做 EnumFont ,该函数是得到所有的字体,假设它的实现是
EnumFont()
{
while ( (f =FindNextFont()) !=NULL)
{
printf("fontname: " + f.name);
}
}
这样就循环显示出所有的字体名称。但是,开发者可能对字体信息另有用处,那么如何才能让开发者能使用这些信息呢,于是做改进:
EnumFont( void* userFunc )
{
while ( (f =FindNextFont()) !=NULL)
{
printf("fontname: " + f.name);
if ( userFunc!=NULL) userFunc( f) ;
}
}
假设userFunc 是一个函数 void f( FontObject font).这样使用者只需要定义一个函数:
void myfunc( FontObject font)
{
listCtrl.Addstring ( font.name);
}
通过使用 EnumFont ( myfunc) 就可以将所有额字体信息添加到一个列表框中。那么我们称 myfunc是一个回调函数,即让某个系统函数调用的函数。因此可以得出结论:
1 回调函数是由开发者按照一定的原型进行定义的函数
2 回调函数并不由发者直接调用执行
3 回调函数通常作为参数传递给系统API,由该API来调用。
4 回调函数可能被系统API调用一次,也可能被循环调用多次。
比如 函数int EnumFontFamilies(
HDC hdc, // handle to device control
LPCTSTR lpszFamily, // pointer to family-name string
FONTENUMPROC lpEnumFontFamProc,
// pointer to callback function
LPARAM lParam // pointer to application-supplied data
);
其中的 FONTENUMPROC lpEnumFontFamProc就是一个回调函数,该函数遵照格式
int CALLBACK EnumFontFamProc( ENUMLOGFONT FAR *lpelf, NEWTEXTMETRIC FAR *lpntm, int FontType, LPARAM lParam )进行定义。
如同mutant所说,回调函数主要用于一些比较费时的操作,或响应不知道何时将会发生的事件,回调函数提供了一种异步的机制,相对于同步执行,提高了效率.前者的例子如WriteFileEx,ReadFileEx等,函数的最后一个参数是一个回调函数的指针,程序中调用WriteFileEx以后,就直接返回了,可以继续进行其他工作,系统在读写操作完成后通知程序作善后处理.后者的例子就是windows的事件机制回调函数的另一个用途,是用于一些枚举函数,如EnumDisplayModes等,每找到一种支持的显示模式,就通知回调函数,由回调函数具体处理,这是因为 EnumDisplayModes本身并不知道用户要如何处理.能,用户提供回调函数,定制系统的功能,这样,不同的用户提供不同的回调函数,可以使系统具有不同的功能.这就是所谓的plugin.使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。
关于回调函数
| clarity 发表于 2005-12-24 15:49:00 | |
关于回调函数
我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函数)有何不同呢? 使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。 而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK(相当于FAR PASCAL),这主要是说明该函数的调用方式。 至于钩子函数,只是回调函数的一个特例。习惯上把与SetWindowsHookEx函数一起使用的回调函数称为钩子函数。也有人把利用VirtualQueryEx安装的函数称为钩子函数,不过这种叫法不太流行。 也可以这样,更容易理解:回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事: 1.声明; 2.定义; 3.设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用。 声明和定义时应注意:回调函数由系统调用,所以可以认为它属于WINDOWS系统,不要把它当作你的某个类的成员函数。
此调用机制并非完美。回调函数就是一例。函数之类本是为调用者准备的美餐,其烹制者应对食客了如指掌,但实情并非如此。例如,写一个快速排序函数供他人调用,其中必包含比较大小。麻烦来了:此时并不知要比较的是何类数据--整数、浮点数、字符串?于是只好为每类数据制作一个不同的排序函数。更通行的办法是在函数参数中列一个回调函数地址,并通知调用者:君需自己准备一个比较函数,其中包含两个指针类参数,函数要比较此二指针所指数据之大小,并由函数返回值说明比较结果。排序函数借此调用者提供的函数来比较大小,借指针传递参数,可以全然不管所比较的数据类型。被调用者回头调用调用者的函数(够咬嘴的),故称其为回调(callback)。 回调函数使程序结构乱了许多。Windows API 函数集中有不少回调函数,尽管有详尽说明,仍使初学者一头雾水。恐怕这也是无奈之举。 无论何种事物,能以树形结构单向描述毕竟让人舒服些。如果某家族中孙辈又是某祖辈的祖辈,恐怕无人能理清其中的头绪。但数据处理之复杂往往需要构成网状结构,非简单的客户/服务器关系能穷尽。 Windows 系统还包含着另一种更为广泛的回调机制,即消息机制。消息本是 Windows 的基本控制手段,乍看与函数调用无关,其实是一种变相的函数调用。发送消息的目的是通知收方运行一段预先准备好的代码,相当于调用一个函数。消息所附带的 WParam 和 LParam 相当于函数的参数,只不过比普通参数更通用一些。应用程序可以主动发送消息,更多情况下是坐等 Windows 发送消息。一旦消息进入所属消息队列,便检感兴趣的那些,跳转去执行相应的消息处理代码。操作系统本是为应用程序服务,由应用程序来调用。而应用程序一旦启动,却要反过来等待操作系统的调用。这分明也是一种回调,或者说是一种广义回调。其实,应用程序之间也可以形成这种回调。假如进程 B 收到进程 A 发来的消息,启动了一段代码,其中又向进程 A 发送消息,这就形成了回调。这种回调比较隐蔽,弄不好会搞成递归调用,若缺少终止条件,将会循环不已,直至把程序搞垮。若是故意编写成此递归调用,并设好终止条件,倒是很有意思。但这种程序结构太隐蔽,除非十分必要,还是不用为好。 利用消息也可以构成狭义回调。上面所举排序函数一例,可以把回调函数地址换成窗口 handle。如此,当需要比较数据大小时,不是去调用回调函数,而是借 API 函数 SendMessage 向指定窗口发送消息。收到消息方负责比较数据大小,把比较结果通过消息本身的返回值传给消息发送方。所实现的功能与回调函数并无不同。当然,此例中改为消息纯属画蛇添脚,反倒把程序搞得很慢。但其他情况下并非总是如此,特别是需要异步调用时,发送消息是一种不错的选择。假如回调函数中包含文件处理之类的低速处理,调用方等不得,需要把同步调用改为异步调用,去启动一个单独的线程,然后马上执行后续代码,其余的事让线程慢慢去做。一个替代办法是借 API 函数 PostMessage 发送一个异步消息,然后立即执行后续代码。这要比自己搞个线程省事许多,而且更安全。 如今我们是活在一个 object 时代。只要与编程有关,无论何事都离不开 object。但 object 并未消除回调,反而把它发扬光大,弄得到处都是,只不过大都以事件(event)的身份出现,镶嵌在某个结构之中,显得更正统,更容易被人接受。应用程序要使用某个构件,总要先弄清构件的属性、方法和事件,然后给构件属性赋值,在适当的时候调用适当的构件方法,还要给事件编写处理例程,以备构件代码来调用。何谓事件?它不过是一个指向事件例程的地址,与回调函数地址没什么区别。 不过,此种回调方式比传统回调函数要高明许多。首先,它把让人不太舒服的回调函数变成一种自然而然的处理例程,使编程者顿觉气顺。再者,地址是一个危险的东西,用好了可使程序加速,用不好处处是陷阱,程序随时都会崩溃。现代编程方式总是想法把地址隐藏起来(隐藏比较彻底的如 VB 和 Java),其代价是降低了程序效率。事件例程(?)使编程者无需直接操作地址,但并不会使程序减速。
回调用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍。其实回调和API非常接近,他们的共性都是跨层调用的函数。但区别是API是低层提供给高层的调用,一般这个函数对高层都是已知的;而回调正好相反,他是高层提供给底层的调用,对于低层他是未知的,必须由高层进行安装,这个安装函数其实就是一个低层提供的API,安装后低层不知道这个回调的名字,但它通过一个函数指针来保存这个回调,在需要调用时,只需引用这个函数指针和相关的参数指针。??? 其实:回调就是该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层那个函数。
对于一般的结构化语言,可以通过回调函数来实现回调。回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。 在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类成为回调类,回调类的对象成为回调对象。对于象C++或Object Pascal这些兼容了过程特性的对象语言,不仅提供了回调对象、回调方法等特性,也能兼容过程语言的回调函数机制。 Windows平台的消息机制也可以作是回调的一种应用,我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。 对于分布式组件代理体系CORBA,异步处理有多种方式,如回调、事件服务、通知服务等。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。对一些简单的异步处理过程,我们可以通过回调机制来实现。 下面我们集中比较具有代表性的语言(C、Object Pascal)和架构(CORBA)来分析回调的实现方式、具体作用等。 2 过程语言中的回调(C)
void Func(char *s);// 函数原型 可以看出,函数的定义和函数指针的定义非常类似。 一般的化,为了简化函数指针类型的变量定义,提高程序的可读性,我们需要把函数指针类型自定义一下。 回调函数可以象普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。 被调函数的例子: void GetCallBack(pcb callback) 如果赋了不同的值给该参数,那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。 2.2 参数传递规则 将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如: // 被调用函数是以int为参数,以int为返回值 // 调用函数以函数指针为参数 // 在p中企图存储被调用函数地址的非法操作 指针p和callee()的类型不兼容,因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列 2.3 应用举例 快速排序函数原型: void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *)); 其中fcmp就是一个回调函数的变量。 下面给出一个具体的例子: #i nclude int sort_function( const void *a, const void *b); int main(void) qsort((void *)list, 5, sizeof(list[0]), sort_function); int sort_function( const void *a, const void *b) 2.4 面向对象语言中的回调(Delphi) Dephi与C++一样,为了保持与过程语言Pascal的兼容性,它在引入面向对象机制的同时,保留了以前的结构化特性。因此,对回调的实现,也有两种截然不同的模式,一种是结构化的函数回调模式,一种是面向对象的接口模式。 | |
List box的右侧滚动条始终处于最低下的方法
如何使List box的右侧滚动条始终处于最低下,以便能显示List box的最后一项的方法
方法1:
CListCtrl.SendMessage(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), NULL);
方法2:
CListCtrl.SetCaretIndex(CListCtrl.GetCount()-1);
堆和栈的区别
堆(heap)和栈(stack)有什么区别??
简单的可以理解为:
heap:是由malloc之类函数分配的空间所在地。地址是由低向高增长的。
stack:是自动分配变量,以及函数调用的时候所使用的一些空间。地址是由高向低减少的。
预备知识—程序的内存分配
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
二、例子程序
这是一个前辈写的,非常详细
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (chr *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}
二、堆和栈的理论知识
2.1申请方式
stack:
由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
如p2 = (char *)malloc(10);
但是注意p1、p2本身是在栈中的。
2.2
申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
2.3申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
2.4申请效率的比较:
栈由系统自动分配,速度较快。但程序员是无法控制的。
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度, 也最灵活
2.5堆和栈中的存储内容
栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
2.6存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指edx中,在根据edx读取字符,显然慢了。
2.7小结:
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
堆和栈的区别主要分:
操作系统方面的堆和栈,如上面说的那些,不多说了。
还有就是数据结构方面的堆和栈,这些都是不同的概念。这里的堆实际上指的就是(满足堆性质的)优先队列的一种数据结构,第1个元素有最高的优先权;栈实际上就是满足先进后出的性质的数学或数据结构。
虽然堆栈,堆栈的说法是连起来叫,但是他们还是有很大区别的,连着叫只是由于历史的原因针值读
PCB设计技巧百问
不同编译器下基本数据长度
KEIL uVision2 C51编译器所支持的数据类型 表中列出了KEIL uVision2 C51编译器所支持的数据类型。在标准C语言中基本的数据类型为char,int,short,long,float和double,而在C51编译器中nt和short相同,float和double相同,这里就不列出说明了。下面来看看它们的具体定义: | |||||||||||||||||||||||||||||||||||||||
|
TorboC编译器的数据长度说明:
整型变量
整型变量可分为以下几类:
1.基本型
类型说明符为int,在内存中占2个字节,其取值为基本整常数。
2.短整量
类型说明符为short int或short'C110F1。所占字节和取值范围均与基本型相同。
3.长整型
类型说明符为long int或long ,在内存中占4个字节,其取值为长整常数。
4.无符号型
类型说明符为unsigned。
无符号型又可与上述三种类型匹配而构成:
(1)无符号基本型 类型说明符为unsigned int或unsigned。
(2)无符号短整型 类型说明符为unsigned short
(3)无符号长整型 类型说明符为unsigned long
各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位,故不能表示负数。 下表列出了Turbo C中各类整型量所分配的内存字节数及数的表示范围。
类型说明符 数的范围 分配字节数
int -32768~32767 ■■
short int -32768~32767 ■■
signed int -32768~32767 ■■
unsigned int 0~65535 ■■
long int -2147483648~2147483647 ■■■■
unsigned long 0~4294967295 ■■■■
在ARM系统应用的数据类型如下 不同编译器可能有所不同
ARM编译器支持的数据类型
************************************************************
数据类型 长度(位) 对齐特性
Char 8 1(字节对齐)
short 16 2(百字对齐)
Int 32 4(字对齐)
Long 32 4(字对齐)
Longlong 64 4(字对齐)
Float 32 4(字对齐)
Double 64 4(字对齐)
Long double 64 4(字对齐)
All pointers 32 4(字对齐)
Bool(C++ only) 32 4(字对齐)
1.整数类型
在ARM体系中,整数类型是以2的补码形式存储的。对于long long类型来说,在little endian内存模式下,其低32位保存在低地址的字单元中,高32为保存在高地址的字单元中;在big endian模式下,其低32位保存在高地址的字单元中,高32为保存在低地址的字单元中。对于整型数据的操作遵守下面的规则:
**所有带符号的整型书的运算是按照二进制的补码进行的。
**带符号的整型数的运算不进行符号的扩展。
**带符号的整型数的右移操作是算数移位。
**制定的移位位数的数是8位的无符号数。
**进行移位操作的数被作为32位数。
**超过31位的逻辑左移的结果为0。
**对于无符号数和有符号的正数来说,超过32位的右移操作结果为0;对于有符号的负数来说,超过32位的右移操作结果为-1。
**整数除法运算的余数和除数有相同的符号。
**当把一个整数截断成位数更短的整数类型的数时,并不能保证所得到的结果的最高位的符号位的正确性。
**整型数据之间的类型转换不会产生异常中断。
**整型数据的溢出不会产生异常中断。
**整型数据除以0将会产生异常中断。
2.浮点数
在ARM体系中,浮点数是按照IEEE标准存储的。
**float类型的数是按照IEEE的单精度数表示的。
**double和long double 是用IEEE的双精度数表示的。
对于浮点数的操作遵守下面的规则:
**遵守正常的IEEE754规则。
**当默认情况下禁止浮点数运算异常中断。
**当发生卷绕时,用最接近的数据来表示。
3.指针类型的数据
下面的规则适用于处数据成员指针以外的其他指针:
**NULL被定义为0。
**相邻的两个存储单元地址相差一。
**在指向函数的指针和指向数据的指针进行数据转换时,编译器将会产生警告信息。
**类型size_t被定义为unsigned int.
**类型ptrdiff_t被定义为signed int。
**两个指针类型的数据相减时,结果可以按照下面的公式得到。
((int)a-(int)b)/(int)sizeof(type pointed to)
这时,只要指针所指的对象不是pack的,其对齐特性能够满足整除的要求。
ARM基础知识八
*****************************************************
ARM编译器中预定义的宏
*****************************************************
ARM编译器预定义了一些宏,这些预定义宏对应一定的数值,有些预定义宏没有对应数值,见下表:
_arm _ 使用编译器armcc,tcc,armcpp,tcpp时
_ARMCC_VERSION Ver 代表编译器版本号,其格式为:
PVtbbb,其中:
P为产品编号(1代表ADS)
V为副版本号(1代表1.1)
T为补丁版本号(0代表1.1)
bbb为build号(比如650)
_APCS_INTERWORK _ 使用编译选项-apcs/interwork时
_APCS_ROPI _ 使用编译选项apcs/ropi时
_RWPI _ 使用编译选项-apcs/rwpi时
_APCS_SWST _ 使用编译选项-apcs/swst时
_BIG_ENDIAN _ 编译器针对目标系统使用big-endian内存模式时
_cplusplus _ 编译器工作与C++模式时
_CC_ARM _ 返回编译器的名称
_DATE_ date 编译源文件的日期
_embedded_cplusplus 编译器工作于EC++模式时
_FEATURE_SINGED_CHAE 使用编译设置选项-zc时设置该预定义宏
_FILE_ name 包含全路径的当前被编译的源文件名称
_func_ name 当前被编译的函数名称
_LINE_ num 当前被编译的代码行号名称
_MOUDLE_ mod 预定义宏_FILE_的文件名称部分
_OPTIMISE_SPACE _ 使用编译选项-OSPACE时
_OPTIMISE_TIME _ 使用编译选项-Otime时
_pretty_func name unmangled的当前函数名称
_sizeof_int 4 sizeof(int),在预处理表达式中可以使用
_sizeof_long 4 sizeof(long),在预处理表达式中可以使用
_sizeof_ptr 4 sizeof(void*)在预处理表达式中可以使用
_SOFTFP _ 编译时使用浮点数
_ _ 在各种编译器模式下
_STDC_VERSION _ 标准的版本信息
_STRICT_ANSI_ _ 使用编译选项-STRICT时
_TARGET_ARCH_xx _ xx代表ARM体系编号
_TARGET_CPU_xx _ xx代表CPU编号
_TARGET_FEATURE_ 当ARM体系支持指令PLD,LDRD,STRD,MCRR,MRRC时
DOUBLEWORD _ 设置该定义宏
_TARGET_FEATURE_ 当系统中包含DSP乘法处理器时,设置该
DSPMUL _ 预定义宏
_TARGET_FEATURE_ 如果目标ARM体系支持半字访问以及有符号的字节数据
HALFWORD _ ,设置该预定义宏
_TARGET_FEATURE_ 如果目标ARM体系支持长乘法指令ULL和
MULTIPLY _ MUAL,设置该预定义宏
_TARGET_FEATURE_ 如果目标ARM体系支持THUMB指令
THUMB _
_TARGET_FPU_xx _ 表示FPU选项,可能取值如下所示:
_TARGET_FPU_VFP
_TARGET_FPU_FPA
_TARGET_FPU_SOFTVFP
_TARGET_FPU_SOFTVFP_VFP
_TARGET_FPU_SOFTFPA
_TARGET_FPU_NONE
_thumb _ 编译器为tcc或tcpp时,设置该预定义宏
_TIME 源文件编译时间
LCD基础及S3C2410 LCD控制器
| LCD基础及S3C2410 LCD控制器 (发布日期:2005-7-13 22:39:46) 浏览人数:374 | |
|
电容器类型和标号
钽电解 CA
复合介质 CH
铌电解 CO
漆膜介质 CQ
铝电解 CD
云母 CY
其它电解 CE
合金电解 CG
高频瓷介 CC
纸介 CZ
低频瓷介 CT
聚苯乙稀 CB
涤纶 CL
聚丙稀 CBB
玻璃膜 CO
聚四氟乙稀 CBF
玻璃釉 CI
聚碳酸脂 CLS
74系列
74系列集成电路大致可分为6大类:
. 74××(标准型);
.74LS××(低功耗肖特基);
.74S××(肖特基);
.74ALS××(先进低功耗肖特基);
.74AS××(先进肖特基);
.74F××(高速)。
近年来还出现了高速CMOS电路的74系列,该系列可分为3大类:
. HC为COMS工作电平;
. HCT为TTL工作电平,可与74LS系列互换使用;
.HCU适用于无缓冲级的CMOS电路。
这9种74系列产品,只要后边的标号相同,其逻辑功能和管脚排列就相同。根据不同的条件和要求可选择不同类型的74系列产品,比如电路的供电电压为3V就应选择74HC系列的产品
系列 电平 典型传输延迟ns 最大驱动电流(-Ioh/Lol)mA
AHC CMOS 8.5 -8/8
AHCT COMS/TTL 8.5 -8/8
HC COMS 25 -8/8
HCT COMS/TTL 25 -8/8
ACT COMS/TTL 10 -24/24
F TTL 6.5 -15/64
ALS TTL 10 -15/64
LS TTL 18 -15/24
LVC
AC
S
LC
注:同型号的74系列、74HC系列、74LS系列芯片,逻辑功能上是一样的。
74LSxx的使用说明如果找不到的话,可参阅74xx或74HCxx的使用说明。
有些资料里包含了几种芯片,如74HC161资料里包含了74HC160、74HC161、
74HC162、74HC163四种芯片的资料。找不到某种芯片的资料时,
可试着查看一下临近型号的芯片资料。
7400 QUAD 2-INPUT NAND GATES 与非门
7401 QUAD 2-INPUT NAND GATES OC 与非门
7402 QUAD 2-INPUT NOR GATES 或非门
7403 QUAD 2-INPUT NAND GATES 与非门
7404 HEX INVERTING GATES 反向器
7406 HEX INVERTING GATES HV 高输出反向器
7408 QUAD 2-INPUT AND GATE 与门
7409 QUAD 2-INPUT AND GATES OC 与门
7410 TRIPLE 3-INPUT NAND GATES 与非门
7411 TRIPLE 3-INPUT AND GATES 与门
74121 ONE-SHOT WITH CLEAR 单稳态
74132 SCHMITT TRIGGER NAND GATES 触发器与非门
7414 SCHMITT TRIGGER INVERTERS 触发器反向器
74153 4-LINE TO 1 LINE SELECTOR 四选一
74155 2-LINE TO 4-LINE DECODER 译码器
74180 PARITY GENERATOR/CHECKER 奇偶发生检验
74191 4-BIT BINARY COUNTER UP/DOWN 计数器
7420 DUAL 4-INPUT NAND GATES 双四输入与非门
7426 QUAD 2-INPUT NAND GATES 与非门
7427 TRIPLE 3-INPUT NOR GATES 三输入或非门
7430 8-INPUT NAND GATES 八输入端与非门
7432 QUAD 2-INPUT OR GATES 二输入或门
7438 2-INPUT NAND GATE BUFFER 与非门缓冲器
7445 BCD-DECIMAL DECODER/DRIVER BCD译码驱动器
7474 D-TYPE FLIP-FLOP D型触发器
7475 QUAD LATCHES 双锁存器
7476 J-K FLIP-FLOP J-K触发器
7485 4-BIT MAGNITUDE COMPARATOR 四位比较器
7486 2-INPUT EXCLUSIVE OR GATES 双端异或门
74HC00 QUAD 2-INPUT NAND GATES 双输入与非门
74HC02 QUAD 2-INPUT NOR GATES 双输入或非门
74HC03 2-INPUT OPEN-DRAIN NAND GATES 与非门
74HC04 HEX INVERTERS 六路反向器
74HC05 HEX INVERTERS OPEN DRAIN 六路反向器
74HC08 2-INPUT AND GATES 双输入与门
74HC107 J-K FLIP-FLOP WITH CLEAR J-K触发器
74HC109A J-K FLIP-FLOP W/PRESET J-K触发器
74HC11 TRIPLE 3-INPUT AND GATES 三输入与门
74HC112 DUAL J-K FLIP-FLOP 双J-K触发器
74HC113 DUAL J-K FLIP-FLOP PRESET 双JK触发器
74HC123A RETRIGGERABLE MONOSTAB 可重触发单稳
74HC125 TRI-STATE QUAD BUFFERS 四个三态门
74HC126 TRI-STATE QUAD BUFFERS 六三态门
74HC132 2-INPUT TRIGGER NAND 施密特触发与非门
74HC133 13-INPUT NAND GATES 十三输入与非门
74HC137 3-TO-8 DECODERS W/LATCHES 3-8线译码器
74HC138 3-8 LINE DECODER 3线至8线译码器
74HC139 2-4 LINE DECODER 2线至4线译码器74HC14 TRIGGERED HEX INVERTER 六触发反向器
74HC147 10-4 LINE PRIORITY ENCODER 10-4编码器
74HC148 8-3 LINE PRIORITY ENCODER 8-3编码器
74HC149 8-8 LINE PRIORITY ENCODER 8-8编码器
74HC151 8-CHANNEL DIGITAL MUX 8通道多路器
74HC153 DUAL 4-INPUT MUX 双四输入多路器
74HC154 4-16 LINE DECODER 4线至16线译码器
74HC155 2-4 LINE DECODER 2线至4线译码器
74HC157 QUAD 2-INPUT MUX 四个双端多路器
74HC161 BINARY COUNTER 二进制计数器
74HC163 DECADE COUNTERS 十进制计数器
74HC164 SERIAL-PARALLEL SHIFT REG 串入并出
74HC165 PARALLEL-SERIAL SHIFT REG 并入串出
74HC166 SERIAL-PARALLEL SHIFT REG 串入并出
74HC173 TRI-STATE D FLIP-FLOP 三态D触发器
74HC174 HEX D FLIP-FLOP W/CLEAR 六D触发器
74HC175 HEX D FLIP-FLOP W/CLEAR 六D触发器
74HC181 ARITHMETIC LOGIC UNIT 算术逻辑单元
74HC182 LOOK AHEAD CARRYGENERATR 进位发生器
74HC190 BINARY UP/DN COUNTER 二进制加减计数器
74HC191 DECADE UP/DN COUNTER 十进制加减计数器
74HC192 DECADE UP/DN COUNTER 十进制加减计数器
74HC193 BINARY UP/DN COUNTER 二进制加减计数器
74HC194 4BIT BI-DIR SHIFT 4位双向移位寄存器
74HC195 4BIT PARALLEL SHIFT 4位并行移位寄存器
74HC20 QUAD 4-INPUT NAND GATE 四个四入与非门
74HC221A NON-RETRIG MONOSTAB 不可重触发单稳
74HC237 3-8 LINE DECODER 地址锁3线至8线译码器
74HC242/243 TRI-STAT TRANSCEIVER 三态收发器
74HC244 OCTAL 3-STATE BUFFER 八个三态缓冲门
74HC245 OCTAL 3-STATE TRANSCEIVER 三态收发器
74HC251 8-CH 3-STATE MUX 8路3态多路器
74HC253 DUAL 4-CH 3-STATE MUX 4路3态多路器
74HC257 QUAD 2-CH 3-STATE MUX 4路3态多路器
74HC258 2-CH 3-STATE MUX 2路3态多路器
74HC259 3-8 LINE DECODER 8位地址锁存译码器
74HC266A 2-INPUT EXCLUSIVE NOR GATE 异或非
74HC27 TRIPLE 3-INPUT NOR GATE三个3输入或非门
74HC273 OCTAL D FLIP-FLOP CLEAR 8路D触发器
74HC280 9BIT ODD/EVEN GENERATOR 奇偶发生器
74HC283 4BIT BINARY ADDER CARRY 四位加法器
74HC299 3-STATE UNIVERSAL SHIFT 三态移位寄存
74HC30 8-INPUT NAND GATE 8输入端与非门
74HC32 QUAD 2-INPUT OR GATE 四个双端或门
74HC34 NON-INVERTER 非反向器
74HC354 8-CH 3-STATE MUX 8路3态多路器
74HC356 8-CH 3-STATE MUX 8路3态多路器
74HC365 HEX 3-STATE BUFFER 六个三态缓冲门
74HC366 3-STATE BUFFER INVERTER 缓冲反向器
74HC367 3-STATE BUFFER INVERTER 缓冲反向器
74HC368 3-STATE BUFFER INVERTER 缓冲反向器
74HC373 3-STATE OCTAL D LATCHES 三态D型锁存器
74HC374 3-STATE OCTAL D FLIPFLOP 三态D触发器
74HC393 4-BIT BINARY COUNTER 4位二进制计数器
74HC4016 QUAD ANALOG SWITCH 四路模拟量开关
74HC4020 14-Stage Binary Counter 14输出计数器
74HC4017 Decade Counter/Divider with 10 Decoded Outputs
十进制计数器带10个译码输出端
74HC4040 12 Stage Binary Counter 12出计数器
74HC4046 PHASE LOCK LOOP 相位监测输出器
74HC4049 LEVEL DOWN CONVERTER 电平变低器
74HC4050 LEVEL DOWN CONVERTER 电平变低器
74HC4051 8-CH ANALOG MUX 8通道多路器
74HC4052 4-CH ANALOG MUX 4通道多路器
74HC4053 2-CH ANALOG MUX 2通道多路器
74HC4060 14-STAGE BINARY COUNTER 14阶BIN计数
74HC4066 QUAD ANALOG MUX 四通道多路器
74HC4075 TRIPLE 3-INPUT OR GATE 3输入或门
74HC42 BCD TO DECIMAL BCD转十进制译码器
74HC423A RETRIGGERABLE MONOSTAB 可重触发单稳
74HC4511 BCD-7 SEG DRIVER/DECODER 7段译码器
74HC4514 4-16 LINE DECODER 4至16线译码器
74HC4538A RETRIGGERAB MONOSTAB 可重触发单稳
74HC4543 LCD BCD-7 SEG LCD用的BCD-7段译码驱动
74HC51 AND OR GATE INVERTER 与或非门
74HC521 8BIT MAGNITUDE COMPARATOR 判决定路
74HC533 3-STATE D LATCH 三态D锁存器
74HC534 3-STATE D FLIP-FLOP 三态D型触发器
74HC540 3-STATE BUFFER 三态缓冲器
74HC541 3-STATE BUFFER INVERTER三态缓冲反向器
74HC58 DUAL AND OR GATE 与或门
74HC589 3STATE 8BIT SHIFT 8位移位寄存三态输出
74HC594 8BIT SHIFT REG 8位移位寄存器
74HC595 8BIT SHIFT REG 8位移位寄存器出锁存
74HC597 8BIT SHIFT REG 8位移位寄存器入锁存
74HC620 3-STATE TRANSCEIVER 反向3态收发器
74HC623 3-STATE TRANSCEIVER 八路三态收发器
74HC640 3-STATE TRANSCEIVER 反向3态收发器
74HC643 3-STATE TRANSCEIVER 八路三态收发器
74HC646 NON-INVERT BUS TRANSCEIVER 总线收发器
74HC648 INVERT BUS TRANCIVER 反向总线收发器
74HC688 8BIT MAGNITUDE COMPARATOR 8位判决电路
74HC7266 2-INPUT EXCLUSIVE NOR GATE 异或非门
74HC73 DUAL J-K FLIP-FLOP W/CLEAR 双JK触发器
74HC74A PRESET/CLEAR D FLIP-FLOP 双D触发器
74HC75 4BIT BISTABLE LATCH 4位双稳锁存器
74HC76 PRESET/CLEAR JK FLIP-FLOP 双JK触发器
74HC85 4BIT MAGNITUDE COMPARATOR 4位判决电路
74HC86 2INPUT EXCLUSIVE OR GATE 2输入异或门
74HC942 BAUD MODEM 300BPS低速调制解调器
74HC943 300 BAUD MODEM 300BPS低速调制解调器
74LS00 QUAD 2-INPUT NAND GATES 与非门
74LS02 QUAD 2-INPUT NOR GATES 或非门
74LS03 QUAD 2-INPUT NAND GATES 与非门
74LS04 HEX INVERTING GATES 反向器
74LS05 HEX INVERTERS OPEN DRAIN 六路反向器
74LS08 QUAD 2-INPUT AND GATE 与门
74LS09 QUAD 2-INPUT AND GATES OC 与门
74LS10 TRIPLE 3-INPUT NAND GATES 与非门
74LS109 QUAD 2-INPUT AND GATES OC 与门
74LS11 TRIPLE 3-INPUT AND GATES 与门
74LS112 DUAL J-K FLIP-FLOP 双J-K触发器
74LS113 DUAL J-K FLIP-FLOP PRESET 双JK触发器
74LS114 NEGATIVE J-K FLIP-FLOP 负沿J-K触发器
74LS122 Retriggerable Monostab 可重触发单稳
74LS123 Retriggerable Monostable 可重触发单稳
74LS125 TRI-STATE QUAD BUFFERS 四个三态门
74LS13 QUAL 4-in NAND TRIGGER 4输入与非触发器
74LS160 BCD DECADE 4BIT BIN COUNTERS 计数器
74LS136 QUADRUPLE 2-INPUT XOR GATE 异或门
74LS138 3-8 LINE DECODER 3线至8线译码器
74LS139 2-4 LINE DECODER 2线至4线译码器
74LS14 TRIGGERED HEX INVERTER 六触发反向器
74HC147 10-4 LINE PRIORITY ENCODER 10-4编码器
74HC148 8-3 LINE PRIORITY ENCODER 8-3编码器
74HC149 8-8 LINE PRIORITY ENCODER 8-8编码器
74LS151 8-CHANNEL DIGITAL MUX 8通道多路器
74LS153 DUAL 4-INPUT MUX 双四输入多路器
74LS155 2-4 LINE DECODER 2线至4线译码器
74LS156 2-4 LINE DECODER/DEMUX 2-4译码器
74LS157 QUAD 2-INPUT MUX 四个双端多路器
74LS158 2-1 LINE MUX 2-1线多路器
74LS160A BINARY COUNTER 二进制计数器
74LS161A BINARY COUNTER 二进制计数器
74LS162A BINARY COUNTER 二进制计数器
74LS163A DECADE COUNTERS 十进制计数器
74LS164 SERIAL-PARALLEL SHIFT REG 串入并出
74LS168 BI-DIRECT BCD TO DECADE 双向计数器
74LS169 4BIT UP/DN BIN COUNTER 四位加减计数器
74LS173 TRI-STATE D FLIP-FLOP 三态D触发器
74LS174 HEX D FLIP-FLOP W/CLEAR 六D触发器
74LS175 HEX D FLIP-FLOP W/CLEAR 六D触发器
74LS190 BINARY UP/DN COUNTER 二进制加减计数器
74LS191 DECADE UP/DN COUNTER 十进制加减计数器
74LS192 DECADE UP/DN COUNTER 十进制加减计数器
74LS193 BINARY UP/DN COUNTER 二进制加减计数器
74LS194A 4BIT BI-DIR SHIFT 4位双向移位寄存器
74LS195A 4BIT PARALLEL SHIFT4位并行移位寄存器
74LS20 QUAD 4-INPUT NAND GATE 四个四入与非门
74LS21 4-INPUT AND GATE 四输入端与门
74LS240 OCTAL 3-STATE BUFFER 八个三态缓冲门
74LS244 OCTAL 3-STATE BUFFER 八个三态缓冲门
74LS245 OCTAL 3-STATE TRANSCEIVER 三态收发器
74LS253 DUAL 4-CH 3-STATE MUX 4路3态多路器
74LS256 4BIT ADDRESS LATCH 四位可锁存锁存器
74LS257 QUAD 2-CH 3-STATE MUX 4路3态多路器
74LS258 2-CH 3-STATE MUX 2路3态多路器
74LS27 TRIPLE 3-INPUT NOR GATES 三输入或非门
74LS279 QUAD R-S LATCHES 四个RS非锁存器
74LS28 QUAD 2-INPUT NOR BUFFER 四双端或非缓冲
74LS283 4BIT BINARY ADDER CARRY 四加法器
74LS30 8-INPUT NAND GATES 八输入端与非门
74LS32 QUAD 2-INPUT OR GATES 二输入或门
74LS352 4-1 LINE SELECTOR/MUX 4-1线选择多路器
74LS365 HEX 3-STATE BUFFER 六个三态缓冲门
74LS367 3-STATE BUFFER INVERTER 缓冲反向器
74LS368A 3-STATE BUFFER INVERTER 缓冲反向器
74LS373 OCT LATCH W/3-STATE OUT三态输出锁存器
74LS76 Dual JK Flip-Flop w/set 2个JK触发器
74LS379 QUAD PARALLEL REG 四个并行寄存器
74LS38 2-INPUT NAND GATE BUFFER 与非门缓冲器
74LS390 DUAL DECADE COUNTER 2个10进制计数器
74LS393 DUAL BINARY COUNTER 2个2进制计数器
74LS42 BCD TO DECIMAL BCD转十进制译码器
74LS48 BCD-7 SEG BCD-7段译码器
74LS49 BCD-7 SEG BCD-7段译码器
74LS51 AND OR GATE INVERTER 与或非门
74LS540 OCT Buffer/Line Driver 8路缓冲驱动器
74LS541 OCT Buffer/LineDriver 8路缓冲驱动器
74LS74 D-TYPE FLIP-FLOP D型触发器
74LS682 8BIT MAGNITUDE COMPARATOR 8路比较器
74LS684 8BIT MAGNITUDE COMPARATOR 8路比较器
74LS75 QUAD LATCHES 双锁存器
74LS83A 4BIT BINARY ADDER CARRY 四位加法器
74LS85 4BIT MAGNITUDE COMPARAT 4位判决电路
74LS86 2INPUT EXCLUSIVE OR GATE 2输入异或门
74LS90 DECADE/BINARY COUNTER 十/二进制计数器
74LS95B 4BIT RIGHT/LEFT SHIFT 4位左右移位寄存
74LS688 8BIT MAGNITUDE COMPARAT 8位判决电路
74LS136 2-INPUT XOR GATE 2输入异或门
74LS651 BUS TRANSCEIVERS 总线收发器
74LS653 BUS TRANSCEIVERS 总线收发器
74LS670 3-STATE 4-BY-4 REG 3态4-4寄存器
74LS73A DUAL J-K FLIP-FLOP W/CLEAR 双JK触发器
CListCtrl应用
void CSimpleServerView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: 在此添加专用代码和/或调用基类
CRect rect;
GetClientRect(rect);
m_pCListCtrl=new CListCtrl;
m_pCListCtrl->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT,rect,this,1);
LV_COLUMN column;
column.pszText="ClientID";
column.mask=LVCF_TEXT;
m_pCListCtrl->InsertColumn(0,&column);
m_pCListCtrl->SetColumnWidth(0,100);
column.pszText="ClientIP";
column.mask=LVCF_TEXT;
m_pCListCtrl->InsertColumn(1,&column);
m_pCListCtrl->SetColumnWidth(1,100);
column.pszText="ClientPort";
column.mask=LVCF_TEXT;
m_pCListCtrl->InsertColumn(2,&column);
m_pCListCtrl->SetColumnWidth(2,100);
column.pszText="Online";
column.mask=LVCF_TEXT;
m_pCListCtrl->InsertColumn(3,&column);
m_pCListCtrl->SetColumnWidth(3,80);
}
增加一项
if (m_pCListCtrl)
{
char temp[9];
strncpy(temp,(char *)pClientInfo->ClientID,8);
temp[8]=0x0;
CString str=temp;
m_pCListCtrl->InsertItem(m_pCListCtrl->GetItemCount(),str);
str.Format("0x%x",pClientInfo->ClientIP);
m_pCListCtrl->SetItemText(m_pCListCtrl->GetItemCount()-1,1,str);
str.Format("%d",pClientInfo->ClientPort);
m_pCListCtrl->SetItemText(m_pCListCtrl->GetItemCount()-1,2,str);
if (pClientInfo->Online==TRUE)
{
m_pCListCtrl->SetItemText(m_pCListCtrl->GetItemCount()-1,3,"TRUE");
}
else
{
m_pCListCtrl->SetItemText(m_pCListCtrl->GetItemCount()-1,3,"FALSE");
}
}