天天看点

C/C++进阶[3]

Point   4   通用指针void *       显然您知道void *是指向任何对象的通用指针。这一点给我们带来很大的方便。考虑下面的例子: typedef   struct      CLISTLINK{        void *pvData;        struct      CLISTLINK*      pre;        struct      CLISTLINK*      next; }CLISTLINK; (一个简单的双向动态链表的链节点类型)       注意到pvData,一个指向数据的通用指针。这意味这该链表是通用链表,它的数据对象类型无限制。但它的“通用性”并不代表它是优雅的实现,该例子主要说明void *的使用,无意讨论哪种实现的优劣。具体实现时您要记住pvData的原类型,以便可以做显式转化来使用数据对象。            转化的一种形式: ( (YourDataType*)pvData ) ->YourDataMember 。 再看一个例子: BOOL   CMP ( void* _a, void*       _b ) { return ((YourDataType*)_a)->_aMember == ((YourDataType*)_b)->_bMember; }        可能您已经注意到,如何进行 YourDataType* 到 void * 的转化?可以隐式进行转化,即 pvData = &YourData ,等价于 pvData = (void *)&YourData 。 Point   5   static 变量      Static 说明适用于外部变量与函数,用于把这些对象的作用域限定为被编译源文件的剩余部分。考虑下面的例子:       //-------------------command.h------------      static      void SaveCmdExplain(HCMDMSG hCmd, char *szCmd);        //body of command.h        //-----------------------------------------------        //---------------------command.c-----------        #include “command.h”        static      void SaveCmdExplain(HCMDMSG hCmd, char *szCmd)        {               //Body of SaveCmdExplain        }        //body of command.c        //---------------------------------------------------        该声明及定义将 SaveCmdExplain 限制于编译单位 command.h 以及 command.h 的实现文件 command.c 内使用。 再考虑下面的例子: char       *StringToLower(char *str) {        static      char szStr[ PATH_MAX_LEN + FILE_NAME_MAX_LEN + 1 ];        //body of StringToLower        return     szStr; } (该函数将字符串 str 转换为小写字符串,返回转换结果的首地址) 注意到 szStr ,它被定义为静态字符串数组。我们称 szStr 为内部静态变量,它像自动变量一样局部于某一特定的函数内,只能在该函数中使用,但与自动变量不同的是,不管其所在函数是否被调用,它都一直存在,而不像自动变量那样,随着所在函数的调用与退出而存在与消失。换而言之,内部静态变量在某一特定函数中使用但一直占据存储空间。这正是我们想要的结果, StringToLower 转换的结果( szStr )必须保留,只有内部静态变量及动态内存分配能提供实现。考虑到动态内存分配涉及对内存的管理,忘记对其回收后会造成内存泄露,故使用自动回收的内部静态变量。