收藏 分享(赏)

C语言内存讲解精品资料.doc

上传人:风样花鼓 文档编号:21124521 上传时间:2023-07-07 格式:DOC 页数:51 大小:281KB
下载 相关 举报
C语言内存讲解精品资料.doc_第1页
第1页 / 共51页
C语言内存讲解精品资料.doc_第2页
第2页 / 共51页
C语言内存讲解精品资料.doc_第3页
第3页 / 共51页
亲,该文档总共51页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

1、c语言中的堆和栈的区别堆和栈的区别1.申请方式(1)栈(satck):由系统自动分配。例如,声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间。(2)堆(heap):需程序员自己申请(调用malloc,realloc,calloc),并指明大小,并由程序员进行释放。容易产生memory leak.eg:char p;p = (char *)malloc(sizeof(char);但是,p本身是在栈中。2.申请大小的限制(1)栈:在windows下栈是向底地址扩展的数据结构,是一块连续的内存区域(它的生长方向与内存的生长方向相反)。栈的大小是固定的。如果申请的空间超过栈的剩余空间时,

2、将提示overflow。(2)堆:堆是高地址扩展的数据结构(它的生长方向与内存的生长方向相同),是不连续的内存区域。这是由于系统使用链表来存储空闲内存地址的,自然是不连续的,而链表的遍历方向是由底地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。3.系统响应:(1)栈:只要栈的空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。(2)堆:首先应该知道操作系统有一个记录空闲内存地址的链表,但系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本

3、次分配的大小,这样,代码中的free语句才能正确的释放本内存空间。另外,找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。说明:对于堆来讲,对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,4.申请效率(1)栈由系统自动分配,速度快。但程序员是无法控制的(2)堆是由malloc分配的内存,一般速度比较慢,而且容易产生碎片,不过用起来最方便。5.堆和栈中的存储内容(1)栈:在函数调用时,第一个进栈的主函数中后的下一条语句的地址,然后是函数的各个参数,参数是从右往左入栈的,然

4、后是函数中的局部变量。注:静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续执行。(2)堆:一般是在堆的头部用一个字节存放堆的大小。6.存取效率(1)堆:char *s1=”hellow tigerjibo”;是在编译是就确定的(2)栈:char s1=”hellow tigerjibo”;是在运行时赋值的;用数组比用指针速度更快一些,指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上读取。补充:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专

5、门的指令执行,这就决定了栈的效率比较高。堆则是C/C+函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。7.分配方式:(1)堆都是动态分配的,没有静态分配的堆。(2)栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的。它的动态分

6、配是由编译器进行释放,无需手工实现。C语言malloc工作机制void *malloc (size_t stSize);该函数在内存的动态存储区中分配 stSize 连续空间,返回值是一个指向所分配的连续存储域的起始地址的指针。void free(void *firstbyte);如果给定一个由先前的 malloc 返回的指针,那么该函数会将分配的空间归还给进程的“空闲空间”。malloc 工作机制:malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块

7、的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。C语言中的时间函数及使用实例#include /* NULL */#include /* ctime, asctime */main()time_t now

8、; /* define now. time_t is probably* a typedef */* Calender time is the number of* seconds since 1/1/1970 */now = time(time_t *)NULL); /* Get the system time and put it* into now as calender time */printf(%s, ctime(&now); /* Format data in now* NOTE that ctime inserts a* n */*/* Here is another way

9、to extract the time/date information */time(&now);printf(%s, ctime(&now); /* Format data in now */*/struct tm *l_time;l_time = localtime(&now); /* Convert calender time to* local time - return a pointer* to the tm structure. localtime* reserves the storage for us. */printf(%s, asctime(l_time);/*/tim

10、e(&now);printf(%s, asctime(localtime( &now );/*/struct tm *l_time;char string20;time(&now);l_time = localtime(&now);strftime(string, sizeof string, %d-%b-%yn, l_time);printf(%s, string);内存管理欢迎进入内存这片雷区。伟大的Bill Gates 曾经失言:640K ought to be enough for everybody Bill Gates 1981程序员们经常编写内存管理程序,往往提心吊胆。如果不想触

11、雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本章的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。7.1内存分配方式内存分配方式有三种:(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员

12、自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。7.2常见的内存错误及其对策发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多没有明显的症状,时隐时现,增加了改错的难度。有时用户怒气冲冲地把你找来,程序却没有发生任何问题,你一走,错误又发作了。常见的内存错误及其对策如下:u 内存分配未成功,却使用了它。编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)

13、进行检查。如果是用malloc或new来申请内存,应该用if(p=NULL) 或if(p!=NULL)进行防错处理。u 内存分配虽然成功,但是尚未初始化就引用它。犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。u 内存分配成功并且已经初始化,但操作越过了内存的边界。例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导

14、致数组操作越界。u 忘记了释放内存,造成内存泄露。含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。u 释放了内存却继续使用它。有三种情况:(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动

15、销毁。(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。l 【规则7-2-1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。l 【规则7-2-2】不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。l 【规则7-2-3】避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。l 【规则7-2-4】动态内存的申请与释放必须配对,防止内存泄漏。l 【规则7-2-5】用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。7.3指针与数组的对比C+

16、/C程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以为两者是等价的。数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。下面以字符串为例比较指针与数组的特性。示例7-3-1中,字符数组a的容量是6个字符,其内容为hello0。a的内容可以改变,如a0= X。指针p指向常量字符串“world”(位于静态存储区,内容为world0),常量字符串的内容是不可以被修改的。

17、从语法上看,编译器并不觉得语句p0= X有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误。char a = “hello”;a0 = X;cout a endl;char *p = “world”; / 注意p指向常量字符串p0 = X; / 编译器不能发现该错误cout p endl;示例7-3-1 修改数组和指针的内容7.3.2 内容复制与比较不能对数组名进行直接复制与比较。示例7-3-2中,若想把数组a的内容复制给数组b,不能用语句 b = a ,否则将产生编译错误。应该用标准库函数strcpy进行复制。同理,比较b和a的内容是否相同,不能用if(b=a) 来判断,应该用标准

18、库函数strcmp进行比较。语句p = a 并不能把a的内容复制指针p,而是把a的地址赋给了p。要想复制a的内容,可以先用库函数malloc为p申请一块容量为strlen(a)+1个字符的内存,再用strcpy进行字符串复制。同理,语句if(p=a) 比较的不是内容而是地址,应该用库函数strcmp来比较。/ 数组char a = hello;char b10;strcpy(b, a); / 不能用 b = a;if(strcmp(b, a) = 0) / 不能用 if (b = a)/ 指针int len = strlen(a);char *p = (char *)malloc(sizeof

19、(char)*(len+1);strcpy(p,a); / 不要用 p = a;if(strcmp(p, a) = 0) / 不要用 if (p = a)示例7-3-2 数组和指针的内容复制与比较用运算符sizeof可以计算出数组的容量(字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了0)。指针p指向a,但是sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。C+/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为

20、同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。char a = hello world;char *p = a;cout sizeof(a) endl; / 12字节cout sizeof(p) endl; / 4字节示例7-3-3(a) 计算数组和指针的内存容量void Func(char a100)cout sizeof(a) endl; / 4字节而不是100字节示例7-3-3(b) 数组退化为指针7.4指针参数是如何传递内存的?如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1中,Test函数

21、的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么?void GetMemory(char *p, int num)p = (char *)malloc(sizeof(char) * num);void Test(void)char *str = NULL;GetMemory(str, 100); / str 仍然为 NULLstrcpy(str, hello); / 运行错误示例7-4-1 试图用指针参数申请动态内存毛病出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。

22、如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例7-4-2。void GetMemory2(char *p, int num)*p = (char *)malloc(sizeof(char) * num);void Test2(void)char *str = NULL

23、;GetMemory2(&str, 100); / 注意参数是 &str,而不是strstrcpy(str, hello);cout str endl;free(str);示例7-4-2用指向指针的指针申请动态内存由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例7-4-3。char *GetMemory3(int num)char *p = (char *)malloc(sizeof(char) * num);return p;void Test3(void)char *str = NULL;str = GetMemory3(100);st

24、rcpy(str, hello);cout str endl;free(str);示例7-4-3 用函数返回值来传递动态内存用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例7-4-4。char *GetString(void)char p = hello world;return p; / 编译器将提出警告void Test4(void)char *str = NULL;str = GetString(); / str 的内容是垃圾cout str endl;示例7-

25、4-4 return语句返回指向“栈内存”的指针用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是“hello world”而是垃圾。如果把示例7-4-4改写成示例7-4-5,会怎么样?char *GetString2(void)char *p = hello world;return p;void Test5(void)char *str = NULL;str = GetString2();cout str endl;示例7-4-5 return语句返回常量字符串函数Test5运行虽然不会出错,但是函数GetString2的

26、设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。7.5 free和delete把指针怎么啦?7.7 杜绝“野指针”“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。“野指针”的成因主要有两种:(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被

27、初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如char *p = NULL;char *str = (char *) malloc(100);(2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。参见7.5节。(3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:class Apublic:void Func(void) cout “Func of class A” Func(); / p是“野指针”函数Test在执行语句p-Func()时,对象a已经消失,而p是指向a的,所以p就成了“野指针”。但奇怪的是我运行这个程序时居

28、然没有出错,这可能与编译器有关。7.8 有了malloc/free为什么还要new/delete ?malloc与free是C+/C语言的标准库函数,new/delete是C+的运算符。它们都可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C+语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内

29、存工作的运算符delete。注意new/delete不是库函数。我们先看一看malloc/free和new/delete如何实现对象的动态内存管理,见示例7-8。class Objpublic :Obj(void) cout “Initialization” endl; Obj(void) cout “Destroy” endl; void Initialize(void) cout “Initialization” endl; void Destroy(void) cout “Destroy” Initialize(); / 初始化/a-Destroy(); / 清除工作free(a); /

30、 释放内存void UseNewDelete(void)Obj *a = new Obj; / 申请动态内存并且初始化/delete a; / 清除并且释放内存示例7-8 用malloc/free和new/delete如何实现对象的动态内存管理类Obj的函数Initialize模拟了构造函数的功能,函数Destroy模拟了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数UseNewDelete则简单得多。所以我们不要企图用malloc/free来完成动态对象的

31、内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。既然new/delete的功能完全覆盖了malloc/free,为什么C+不把malloc/free淘汰出局呢?这是因为C+程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete必须配对使用,malloc/free也

32、一样。7.9 内存耗尽怎么办?如果在申请动态内存时找不到足够大的内存块,malloc和new将返回NULL指针,宣告内存申请失败。通常有三种方式处理“内存耗尽”问题。(1)判断指针是否为NULL,如果是则马上用return语句终止本函数。例如:void Func(void)A *a = new A;if(a = NULL)return;(2)判断指针是否为NULL,如果是则马上用exit(1)终止整个程序的运行。例如:void Func(void)A *a = new A;if(a = NULL)cout “Memory Exhausted” endl;exit(1);(3)为new和mall

33、oc设置异常处理函数。例如Visual C+可以用_set_new_hander函数为new设置用户自己定义的异常处理函数,也可以让malloc享用与new相同的异常处理函数。详细内容请参考C+使用手册。上述(1)(2)方式使用最普遍。如果一个函数内有多处需要申请动态内存,那么方式(1)就显得力不从心(释放内存很麻烦),应该用方式(2)来处理。很多人不忍心用exit(1),问:“不编写出错处理程序,让操作系统自己解决行不行?”不行。如果发生“内存耗尽”这样的事情,一般说来应用程序已经无药可救。如果不用exit(1) 把坏程序杀死,它可能会害死操作系统。道理如同:如果不把歹徒击毙,歹徒在老死之前

34、会犯下更多的罪。有一个很重要的现象要告诉大家。对于32位以上的应用程序而言,无论怎样使用malloc与new,几乎不可能导致“内存耗尽”。我在Windows 98下用Visual C+编写了测试程序,见示例7-9。这个程序会无休止地运行下去,根本不会终止。因为32位操作系统支持“虚存”,内存用完了,自动用硬盘空间顶替。我只听到硬盘嘎吱嘎吱地响,Window 98已经累得对键盘、鼠标毫无反应。我可以得出这么一个结论:对于32位以上的应用程序,“内存耗尽”错误处理程序毫无用处。这下可把Unix和Windows程序员们乐坏了:反正错误处理程序不起作用,我就不写了,省了很多麻烦。我不想误导读者,必须强

35、调:不加错误处理将导致程序的质量很差,千万不可因小失大。void main(void)float *p = NULL;while(TRUE)p = new float1000000;cout “eat memory” endl;if(p=NULL)exit(1);示例7-9试图耗尽操作系统的内存7.10 malloc/free 的使用要点函数malloc的原型如下:void * malloc(size_t size);用malloc申请一块长度为length的整数类型的内存,程序如下:int *p = (int *) malloc(sizeof(int) * length);我们应当把注意力集

36、中在两个要素上:“类型转换”和“sizeof”。u malloc返回值的类型是void *,所以在调用malloc时要显式地进行类型转换,将void * 转换成所需要的指针类型。u malloc函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。我们通常记不住int, float等数据类型的变量的确切字节数。例如int变量在16位系统下是2个字节,在32位下是4个字节;而float变量在16位系统下是4个字节,在32位下也是4个字节。最好用以下程序作一次测试:cout sizeof(char) endl;cout sizeof(int) endl;cout sizeof(unsig

37、ned int) endl;cout sizeof(long) endl;cout sizeof(unsigned long) endl;cout sizeof(float) endl;cout sizeof(double) endl;cout sizeof(void *) endl;在malloc的“()”中使用sizeof运算符是良好的风格,但要当心有时我们会昏了头,写出 p = malloc(sizeof(p)这样的程序来。u 函数free的原型如下:void free( void * memblock );为什么free函数不象malloc函数那样复杂呢?这是因为指针p的类型以及它所指

38、的内存的容量事先都是知道的,语句free(p)能正确地释放内存。如果p是NULL指针,那么free对p无论操作多少次都不会出问题。如果p不是NULL指针,那么free对p连续操作两次就会导致程序运行错误。7.11 new/delete 的使用要点运算符new使用起来要比函数malloc简单得多,例如:int *p1 = (int *)malloc(sizeof(int) * length);int *p2 = new intlength;这是因为new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数

39、,那么new的语句也可以有多种形式。例如class Objpublic :Obj(void); / 无参数的构造函数Obj(int x); / 带一个参数的构造函数void Test(void)Obj *a = new Obj;Obj *b = new Obj(1); / 初值为1delete a;delete b;如果用new创建对象数组,那么只能使用对象的无参数构造函数。例如Obj *objects = new Obj100; / 创建100个动态对象不能写成Obj *objects = new Obj100(1);/ 创建100个动态对象的同时赋初值1在用delete释放对象数组时,留意

40、不要丢了符号。例如delete objects; / 正确的用法delete objects; / 错误的用法后者相当于delete objects0,漏掉了另外99个对象。7.12 一些心得体会我认识不少技术不错的C+/C程序员,很少有人能拍拍胸脯说通晓指针与内存管理(包括我自己)。我最初学习C语言时特别怕指针,导致我开发第一个应用软件(约1万行C代码)时没有使用一个指针,全用数组来顶替指针,实在蠢笨得过分。躲避指针不是办法,后来我改写了这个软件,代码量缩小到原先的一半。我的经验教训是:(1)越是怕指针,就越要使用指针。不会正确使用指针,肯定算不上是合格的程序员。(2)必须养成“使用调试器逐

41、步跟踪程序”的习惯,只有这样才能发现问题的本质。1. API之网络函数WNetAddConnection 创建同一个网络资源的永久性连接WNetAddConnection2 创建同一个网络资源的连接WNetAddConnection3 创建同一个网络资源的连接WNetCancelConnection 结束一个网络连接WNetCancelConnection2 结束一个网络连接WNetCloseEnum 结束一次枚举操作WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接WNetDisconnectDialog 启动一个标准对话框,以便断开同网络资源的连接WNe

42、tEnumResource 枚举网络资源WNetGetConnection 获取本地或已连接的一个资源的网络名称WNetGetLastError 获取网络错误的扩展错误信息WNetGetUniversalName 获取网络中一个文件的远程名称以及/或者UNC(统一命名规范)名称WNetGetUser 获取一个网络资源用以连接的名字WNetOpenEnum 启动对网络资源进行枚举的过程2. API之消息函数BroadcastSystemMessage 将一条系统消息广播给系统中所有的顶级窗口GetMessagePos 取得消息队列中上一条消息处理完毕时的鼠标指针屏幕位置GetMessageTim

43、e 取得消息队列中上一条消息处理完毕时的时间PostMessage 将一条消息投递到指定窗口的消息队列PostThreadMessage 将一条消息投递给应用程序RegisterWindowMessage 获取分配给一个字串标识符的消息编号ReplyMessage 答复一个消息SendMessage 调用一个窗口的窗口函数,将一条消息发给那个窗口SendMessageCallback 将一条消息发给窗口SendMessageTimeout 向窗口发送一条消息SendNotifyMessage 向窗口发送一条消息3. API之文件处理函数CloseHandle 关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等CompareFileTime 对比两个文件的时间CopyFile 复制文件CreateDirectory 创建一个新目录CreateFile 打开和创建文件、管道、邮槽、通信服务、设备以及控制台CreateFileMapping 创建一个新的文件映射对象DeleteFile 删除指定文件DeviceIoControl 对设备执行指定的操作DosDateTimeToFileTime 将DOS日期和时间值转换成一个 win32 FILETIME 值FileTimeToDosDateTime 将一个

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 网络科技 > 其他相关文档

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报