首页 > 代码库 > C和C++格式转换
C和C++格式转换
一、引用参数和指针的转换
标准C不支持引用参数,对此需进行转换。下面以bo1-1.cpp和bo1-1.c中DestroyTriplet()函数为例来说明这种转换。
bo1-1.cpp中含有引用参数的函数如下:
1 Status DestroyTriplet(Triplet &T) { 2 // 操作结果:三元组T被销毁 3 free(T); 4 T=NULL; 5 return OK; 6 }
转换后在bo1-1.c中的标准C程序如下:
1 Status DestroyTriplet(Triplet *T) /* 将&T改为*T */ 2 { /* 操作结果:三元组T被销毁*/ 3 free(*T); /* 将T改为*T */ 4 *T=NULL; /* 将T改为*T */ 5 return OK; 6 }
对照以上2个函数可见:将C++函数形参表中以&打头的参数改成以*打头的参数,再在函数中该参数前加*即可。
要注意的是,在这两个函数中,形参的类型是不同的。在bo1-1.cpp中,T的类型是Triplet;在bo1-1.c 中,T的类型是Triplet的指针。
但为方便起见,没有改写C程序中的注释。另外,在标准C程序中调用该函数,实参前应加&。
如main1-1.cpp中调用DestroyTriplet()的语句为
1 DestroyTriplet(T);
相应的标准C程序main1-1.c 中调用DestroyTriplet()的语句为
1 DestroyTriplet(&T);
其中,在调用DestroyTriplet()的两程序中,两实参T的类型是相同的。
另外,在转换过程中,遇到&*或*&可“抵消”,即将*&T转换为T。
二、标准C在指明所定义的结构体或枚举类型时,在类型前要加strutc或enum,而C++则不必加
如在C++的c2-1.h中定义结构体SqList如下:
1 struct SqList { 2 ElemType *elem; // 存储空间基址 3 int length; // 当前长度 4 int listsize; // 当前分配的存储容量(以sizeof(ElemType)为单位) 5 };
C++在指明变量或形参的类型时,只需用SqList即可。如bo2-1.cpp中的一个函数如下:
1 int ListLength(SqList L) { 2 // 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 3 return L.length; 4 }
如果在标准C程序中像C++的c2-1.h那样定义变量L的类型,则在bo2-1.c中该函数应如下:
1 int ListLength(struct SqList L) { 2 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数*/ 3 return L.length; 4 }
说明变量L时要用struct SqList。当用到某个结构体就要在其类型前加struct,用到某个枚举类型就要在其类型前加enum是很麻烦的。
为了方便起见,可用typedef定义类型。在标准C程序的c2-1.h中定义SqList如下:
1 typedef struct { 2 ElemType *elem; /* 存储空间基址*/ 3 int length; /* 当前长度*/ 4 int listsize; /* 当前分配的存储容量(以sizeof(ElemType)为单位) */ 5 }SqList;
这样,在bo2-1.c中相应的函数为
1 int ListLength(SqList L) { 2 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数*/ 3 return L.length; 4 }
这个函数与bo2-1.cpp 很相似。可见,只要在定义结构体时使用typedef,则在指明结构体的类型时就不必加struct。
标准C都采用这种方法定义结构体。定义枚举类型时使用typedef 的方法与此类似。
三、标准C的共用体必须有变量名,而C++可以省略
如在c5-6.h(C++)中定义GLNode1如下:
1 // c5-6.h 广义表的扩展线性链表存储结构 2 enum ElemTag{ATOM,LIST}; // ATOM==0:原子,LIST==1:子表 3 typedef struct GLNode1 { 4 ElemTag tag; // 公共部分,用于区分原子结点和表结点 5 union // 原子结点和表结点的联合部分 6 { 7 AtomType atom; // 原子结点的值域 8 GLNode1 *hp; // 表结点的表头指针 9 }; 10 GLNode1 *tp; // 相当于线性链表的next,指向下一个元素结点 11 }*GList1,GLNode1; // 广义表类型GList1是一种扩展的线性链表
注意:其中的共用体没有变量名。在bo5-6.cpp 中的函数GListEmpty()如下:
1 Status GListEmpty(GList1 L) { 2 // 初始条件:广义表L存在。操作结果:判定广义表L是否为空 3 if(!L||L->tag==LIST&&!L->hp) 4 return OK; 5 else 6 return ERROR; 7 }
而标准C的c5-6.h如下:
1 /* c5-6.h 广义表的扩展线性链表存储结构*/ 2 typedef enum{ATOM,LIST}ElemTag; /* ATOM==0:原子,LIST==1:子表*/ 3 typedef struct GLNode1 { 4 ElemTag tag; /* 公共部分,用于区分原子结点和表结点*/ 5 union /* 原子结点和表结点的联合部分*/ 6 { 7 AtomType atom; /* 原子结点的值域*/ 8 struct GLNode1 *hp; /* 表结点的表头指针*/ 9 }a; 10 struct GLNode1 *tp; /* 相当于线性链表的next,指向下一个元素结点*/ 11 }*GList1,GLNode1; /* 广义表类型GList1是一种扩展的线性链表*/
它内部的共用体必须有变量名。在bo5-6.c 的函数GListEmpty()中也变动如下:
1 Status GListEmpty(GList1 L) { 2 /* 初始条件:广义表L存在。操作结果:判定广义表L是否为空*/ 3 if(!L||L->tag==LIST&&!L->a.hp) 4 return OK; 5 else 6 return ERROR; 7 }
四、C++可重载
即在一个程序中,可有几个同名的函数同时存在。只要它们的形参个数或类型有所不同即可。
标准C不可重载。在C++转换成标准C时,必须将同名函数改为不同名。
如在bo9-2.cpp中有1个SearchBST()函数(算法9.5(b)),在bo9-2.cpp所包含的文件func9-1.cpp中也有1个SearchBST()函数(算法9.5(a)),但这两个同名函数的形参个数不同。
C++根据函数的形参个数可分辨所调用的是哪个函数。而标准C没有这个能力,所以把bo9-2.c中的SearchBST()函数改为SearchBST1()函数。
五、C++允许在执行语句中变量使用之前定义变量
如algo8-1.cpp 中的PrintUser()函数:
1 void PrintUser(Space p[]) { 2 // 输出p数组所指的已分配空间 3 for(int i=0;i<MAX/e;i++) 4 if(p[i]) // 指针不为0(指向一个占用块) { 5 printf("块%d的首地址=%u ",i,p[i]); // 输出结点信息 6 printf("块的大小=%d 块头标志=%d(0:空闲1:占用)",p[i]->size,p[i]->tag); 7 printf(" 块尾标志=%d\n",(FootLoc(p[i]))->tag); 8 } 9 }
这种形式在标准C 语言中是不允许的。相应的algo8-1.c 中的PrintUser()函数为:
1 void PrintUser(Space p[]) { 2 /* 输出p数组所指的已分配空间*/ 3 int i; 4 for(i=0;i<MAX/e;i++) 5 if(p[i]) /* 指针不为0(指向一个占用块) */ { 6 printf("块%d的首地址=%u ",i,p[i]); /* 输出结点信息*/ 7 printf("块的大小=%d 块头标志=%d(0:空闲1:占用)",p[i]->size,p[i]->tag); 8 printf(" 块尾标志=%d\n",(FootLoc(p[i]))->tag); 9 } 10 }
六、C++允许在转换类型时采用函数的形式
如algo8-2.cpp中AllocBuddy()函数的,一条语句如下:
1 pi=pa+int(pow(2,k-i));
而在标准C程序algo8-2.c中必须改为以下形式(注意带下划线部分):
1 pi=pa+(int)pow(2,k-i);
七、在C++中可用new申请空间
如bo8-1.cpp 中主函数main()的一条语句如下:
1 p=new WORD[MAX+2]; // 申请大小为MAX*sizeof(WORD)个字节的空间
在标准C的bo8-1.c中要改为
1 p=(WORD*)malloc((MAX+2)*sizeof(WORD)); /* 申请大小为MAX*sizeof(WORD)个字节的空间*/
八、在C++中可用cout和cin做输入输出语句
它们的好处是不必给出格式符。这样,当变量的类型发生变化时,不必修改语句。但在main1-1.c 中必须改为
1 printf("%d %d %d\n",T[0],T[1],T[2]);/*当ElemType的类型变化时,要相应改变printf()的格式符*/
九、在C++中“//”后到本行末的内容为注释,而标准C的注释必须放在“/*”、“*/”之间
十、标准C 程序的扩展名为.c,C++程序的扩展名为.cpp
定义数据存储结构的文件,其扩展名是.h,在两种语言中不能混用。
C和C++格式转换