博文

work thread和UI thread的区别(包括产生以及终结)(2010-03-23 18:55:00)

摘要:一、线程产生篇: 它们都需要呼叫AfxBeginThread 以产生一个 CWinThread 对象,并在创建对象的时候定义其消息响应函数,下面代码是work thread所呼叫的AfxBeginThread函数: CWinThread* pThread = AfxBeginThread(ThreadFunc, &Param); 函数原型是: CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL); 但如果要产生一个UI thread,你还必须先定义一个 CWinThread 衍生类别,因为现在需要一个消息回路,CWinThread::Run里头就有一个消息回路,然后再呼叫AfxBeginThread产生一个CWinThread对象。下面代码是UI thread所呼叫的AfxBeginThread()函数: CWinThread *pThread = AfxBeginThread(RUNTIME_CLASS(CMyThread)); 函数原型是: CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL); 注意:UI thread的消息响应函数原型和work thread的消息响应函数是两个不同的重载函数。 二、线程结束篇 既然 worker thread 的生命就是线程函数本身,函数一旦 return,线程也就结束了,自然得很。或者线程函数也可以呼叫 AfxEndThread,结束一个线程。UI 线程因为有消息回路的关系,必须在消息队列中放一个 WM......

阅读全文(3276) | 评论:0

用函数指针变量调用函数(2009-10-28 10:33:00)

摘要:可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配给一个入口地址。这个入口地址就称为函数的指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。先通过一个简单的例子来回顾一下函数的调用情况。例 求a和b中的大者。先列出按一般方法的程序。main(){   int max(int,int);   int a,b,c;   scanf("%d,%d",&a,&b);   c=max(a,b);   printf("a=%d,b=%d,max=%d",a,b,c);}max(int x,int y){   int z;   if(x>y) z=x;   else z=y;   return(z);}  main 函数中的“c=max(a,b);”包括了一次函数调用(调用 max 函数)。每一个函数都占用一段内存单元,它们有一个起始地址。因此,可以用一个指针变量指向一个函数,通过指针变量来访问它指向的函数。  将 main 函数改写为main(){   int max(int,int);   int (*p)();   int a,b,c;   p=max;   scanf("%d,%d",&a,&b);   c=(*p)(a,b);   printf("a=%d,b=%d,max=%d",a,b,c);}  其中“int (*p)();”定义 p 是一个指向函数的指针变量,此函数带回整型的返回值。注意 *p 两侧的括弧不可省略,表示 p 先与 * 结合,是指针变量,然后再与后面的()结合,表示此指针变量指向函数,这个函数值(即函数返回的值)是整型的。如果写成“int *p();”,则由于()优先级高于*,它就成了声明一个......

阅读全文(5196) | 评论:0

assert() 函数用法(2009-10-22 10:12:00)

摘要:assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: #include <assert.h> void assert( int expression ); assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息, 然后通过调用 abort 来终止程序运行。 请看下面的程序清单badptr.c: #include <stdio.h> #include <assert.h> #include <stdlib.h> int main( void ) {        FILE *fp;            fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件        assert( fp );                           //所以这里不会出错        fclose( fp );            fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败        assert( fp );          &n......

阅读全文(1757) | 评论:0

C++为什么不支持类模板的声明与实现的分离?(2009-09-28 15:35:00)

摘要:【转】http://www.pexwin.cn/Topic.aspx?BoardID=2&TopicID=291 C++不支持类模板的声明与实现分离: 普通的实例: \***********THead.h*********\ class TA {     int a; public:     TA(); } \*********THead.cpp*********\ TA::TA() { } \*********tmain.cpp********\ #include "THead.h" #include <iostream> using namespace std; int main() {    TA ta; } \************************\ 分析:   编译main.cpp时,要调用TA的构造函数,但main.cpp没有,所以去"THead.h"找;找到THead.h时也没有找到,所以去所在的目录里找,结果找到了THead.cpp,编译了THead.cpp产生THead.obj,至此已完成了ta的构造. 过程为:   编译:main.cpp生成main.obj,THead.obj 运行连接:   首先加载main.obj,发现没有TA的构造函数模块,于是连接THead.obj找到并继续运行。 模板的实例: \**********Test.h**********\ template<typename T> class A {     int a; public:     A(); }; \*********Test.cpp********\ template<typename T> A<T>::A() { } \********main.cpp*********\ #include "Test.h" #include <iosteram> using namespace std; int main() {   &nb......

阅读全文(3185) | 评论:1

ASCII表(2009-09-20 21:33:00)

摘要: ASCII表 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 0 NUT 32 (space) 64 @ 96 、 1 SOH 33 ! 65 A 97 a 2 STX 34 ” 66 B 98 b 3 ETX 35 # 67 C 99 c 4 EOT 36 $ 68 D 100 d 5 ENQ 37 % 69 E 101 e 6 ACK 38 & 70 F 102 f 7 BEL 39 , 71 G 103 g 8 BS 40 ( 72 H 104 h 9 HT 41 ) 73 I 105 i 10 LF 42 * 74 J 106 j 11 VT 43 + 75 K 107 k 12 FF 44 , 76 L 108 l 13 CR 45 - 77 M 109 m 14 SO 46 . 78 N 110 n 15 SI 47 / 79 O 111 o 16 DLE 48 0 80 P 112 p 17 DCI 49 1 81 Q 113 q 18 DC2 50 2 82 R 114 r 19 DC3 51 3 83 X 115 s 20 DC4 52 4 84 T 116 t 21 NAK 53 5 85 U 117 u 22 SYN 54 6 86 V 118 v 23 TB 55 7 87 W 119 w 24 CAN 56 8 88 X 120 x 25 EM 57 9 89 Y 121 y 26 SUB 58 : 90 Z 122 z 27 ESC 59 ; 91 [ 123 { 28 FS 60 <......

阅读全文(1858) | 评论:0

C++文件读写函数介绍(2009-09-16 20:56:00)

摘要:1.fopen()   fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能:为使用而打开一个流,把一个文件和此流相连接,给此流返回一个FILR指针。  参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下:   字符串 含义   "r" 以只读方式打开文件   "w" 以只写方式打开文件   "a" 以追加方式打开文件   "r+" 以读/写方式打开文件,如无文件出错   "w+" 以读/写方式打开文件,如无文件生成新文件   一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符’\n’,而二进制模式认为它是两个字符0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。   系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。   我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。   此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL.  例:    以下是引用片段: FILE *fp;    if(fp=fopen("123.456","wb"))    puts("打开文件成功");    else    puts("打开文件成败");   2.fclose()   fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。   在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这......

阅读全文(4745) | 评论:0

linux下用gcc生成静态库和动态库(2009-09-15 10:11:00)

摘要: 蛮清楚的。 我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。 在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。 第1步:编辑得到举例的程序--hello.h、hello.c和main.c; hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"Hello XXX!"。hello.h(见程序1)为该函数库的头文件。main.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello。 #ifndef HELLO_H#define HELLO_H void hello(const char *name); #endif //HELLO_H程序1: hello.h #include <stdio.h> void hello(const char *name){printf("Hello %s!\n", name);}程序2: hello.c #include "hello.h" int main(){hello("everyone");return 0;}程序3: main.c 第2步:将hello.c编译成.o文件; 无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。 在系统提示符下键入以下命令得到hello.o文件。 # gcc -c hello.c # 我们运行ls命令看看是否生存了hello.o文件。 # ls hello.c hello.h hello.o main.c # 在ls命令结果中,我们看到了hello.o文件,本步操作完成。 下面我们先来看看如何创建静态库,以及使用它。 第3步:由.o文件创建静态库; 静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和......

阅读全文(3590) | 评论:1

linux下用gcc生成静态库和动态库(2009-09-15 10:11:00)

摘要: 蛮清楚的。 我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。 在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。 第1步:编辑得到举例的程序--hello.h、hello.c和main.c; hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"Hello XXX!"。hello.h(见程序1)为该函数库的头文件。main.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello。 #ifndef HELLO_H#define HELLO_H void hello(const char *name); #endif //HELLO_H程序1: hello.h #include <stdio.h> void hello(const char *name){printf("Hello %s!\n", name);}程序2: hello.c #include "hello.h" int main(){hello("everyone");return 0;}程序3: main.c 第2步:将hello.c编译成.o文件; 无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。 在系统提示符下键入以下命令得到hello.o文件。 # gcc -c hello.c # 我们运行ls命令看看是否生存了hello.o文件。 # ls hello.c hello.h hello.o main.c # 在ls命令结果中,我们看到了hello.o文件,本步操作完成。 下面我们先来看看如何创建静态库,以及使用它。 第3步:由.o文件创建静态库; 静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和......

阅读全文(1698) | 评论:0

Linux下静态库.a文件生成方法(转)(2009-09-14 16:53:00)

摘要:Linux下静态库.a生成1.将各函数代码所在的源文件编译成目录文件。例如,对于myfunc.c,可以用如下命令 将其编译成目标文件: gcc -c myfunc.c 当然在有多个源文件时,只需在gcc 命令行中将其分别列上就可以了。经此一步,将能够得到各源文件的目标文件。对上例,将得到myfunc.o 2.将各目标文件收集起来放到一个静态库文件中。这主要借助于ar命令完成,如: ar r ~/lib/libtest.a myfunc.o 注:建立动态链接库、并不需要用到其他的工具,借助于gcc命令即可完成。此时需在命令 行中加上-K  PIC和-G这两个选项,如下我们可以建立libtest的动态版本:gcc -K PIC -G -o $HOME/lib/libtest.so myfunc.c 1、用gcc的-c选项生成.o文件,如gcc -c test1.c test2.c test3.c编译后会生成test1.o test2.o test3.o三个目标文件。2、然后用ar命令生成.a文件,如ar crv test.a test1.o test2.o test3.o   本文来自CSDN博客,http://blog.csdn.net/zhangbiao1981/archive/2009/04/27/4128209.aspx......

阅读全文(3290) | 评论:0

bind1st bind2nd的使用(转)(2009-09-11 20:45:00)

摘要: 作者Blog:http://blog.csdn.net/simahao/ 本篇适合不熟悉这两个函数的读者         以前在使用stl的过程中发现bind1st和bind2nd这两个函数,当时不太理解什么意思,今天在网上查了一下相关资料发现竟然很简单,下面我就具体解释一下他们的用法。         bind1st和bind2nd函数用于将一个二元算子(binary functor,bf)转换成一元算子(unary functor,uf)。为了达到这个目的,它们需要两个参数:要转换的bf和一个值(v)。          可能这么解释以后大家还不是很清楚,那么就说点白话吧。我们在做比较的时候所写的表达式像 x > k ,x < k,这里的k是一个参数表示你程序里面的表达式要和k值去比较。上面这两个表达式对应的应该是bind2nd ,简单的理解就是把k作为比较表达式的第二个参数。如果使用bind1st则对应的表达式是 k > x,k < x,也就是把k作为比较表达式的第一个参数。大家可能会注意到这里面没有=的比较,先别着急,后面将会说道如何实现=的比较。先举两个例子看看bind1st和bind2nd的用法。 int a[] = {1, 2, 100, 200}; std::vector< int> arr(a, a + 4);// 移除所有小于100的元素arr.erase( std::remove_if( arr.begin(),  arr.end(),    std::bind2nd( std::less< int>(), 100)), arr.end()); 这里的比较表达式相当于arr.value < 100 如果用bind1st则表达的意思就恰恰相反 // 移除所有大于100的元素arr.erase( std::remove_if( arr.begin(),  ar......

阅读全文(2683) | 评论:0