最近C++代码写得比较多,感觉泛形蛮实用的,而且我一直都觉得语言都是相通的,一样的需求,在不同的语言中应该都是能够得到实现的,只是表述方式有所不同。对于某种功能,有的语言可能实现起来比较复杂,有的语言由于自身特性则相对简单,但是所有的语言应该都是能够实现这样的功能的,只是有些方法还没有想到而已,所以不存在某种功能是某种语言所独有的(个人观点)。
同理,看到泛型这么实用,而且C++,Java都存在泛形,于是我觉得C语言也应该有泛形,虽然C语言本身没有对泛形的支持(据我所知),但是肯定有方法能够实现,或许这个方法会很笨拙,但是绝对存在。
下面是我思索过后,得出的方法(这个过程肯定是写了不只一段测试代码的,但是错误的方法就没必要列出来了,这里只给出目前所能想到的比较好的方法):
以我给出的代码为例子,我这里实现了一个能够自定义长度的数组,数组的类型为Ary_Var , 数组长度存放在arySize中,该数据结构的定义如下:
typedef struct VarArray VarArray ;
struct VarArray {
Ary_Var *varAry ; // 定义一个类型为Ary_Var的指针,
// 用于创建一个动态申请空间的数组
// 此处Ary_Var的类型未定(这是泛形的关键)
int arySize ; //存放数组长度
} ;
然后借助于C语言的条件编译让Ary_Var类型在编译时能够被确定,因为在C语言中,变量的类型在编译时必须是确定的,否则就会报错,所以要借助于条件编译让Ary_Var在编译时被替换为C语言的合法类型(int , float或其他类型)。具体实现:将上述实现的数据结构放在一个头文件中,并且在该头文件中,以条件编译的方式,指定在不同编译条件下Ary_Var的实际类型,具体代码如下:
头文件:VarArray.h
# ifndef VarArray_h
# define VarArray_h
# ifdef Ary_INT
# define Ary_Var int //当Ary_INT被定义,则Ary_Var的实际类型为int
# endif
# ifdef Ary_LONG
# define Ary_Var long //当Ary_LONG被定义,则Ary_Var的实际类型为long
# endif
# ifdef Ary_CHAR
# define Ary_Var char //当Ary_CHAR被定义,则Ary_Var的实际类型为char
# endif
# ifdef Ary_FLOAT
# define Ary_Var float //当Ary_FLOAT被定义,则Ary_Var的实际类型为float
# endif
# include <stdlib.h>
typedef struct VarArray VarArray ;
struct VarArray {
Ary_Var *varAry ; //定义一个类型为Ary_Var的指针,
//用于创建一个动态申请空间的数组
//此处Ary_Var的类型未定(这是泛形的关键)
int arySize ; //存放数组长度
} ;
/*
* 数组的初始化方法,通过定义含有参数的宏来实现
* (注意:为数组申请空间malloc时,
* 也采用未定类型Ary_Var,而没有采用具体类型)
*/
# define aryInit(Ary, size) {\
Ary.arySize = size ;\
Ary.varAry = (Ary_Var *) malloc ( size * sizeof (Ary_Var)) ;\
}
# endif
此外还需要一个头文件,用于关闭VarArray.h中通过#define所定义的宏,因为在C语言中用户通过#define所定义的的宏,从定义处开始到文件末尾都是可用的,而此处实现的可自定义长度的泛型数组可能会在同一个文件中多处用到,故需要关闭相关宏,以避免干扰。具体代码如下:
头文件:AryEnd.h
# undef Ary_Var
# undef VarArray
# undef aryInit
# undef VarArray_h
接下来编写测试代码,具体实现如下:
源文件:Test.c
# include <stdio.h>
void showInt ()
{
/*
* 运用VarArray.h中实现的可自定义长度的泛型数组来存储int型数据
*/
# define Ary_INT //指定泛型数组的类型为int
# include "VarArray.h" //导入泛型数组的定义,并将数组类型确定为int
# undef Ary_INT //关闭宏
int i ;
enum {NUM = 2} ; //用常量来指定数组的长度(长度为2)
VarArray test ; //实例化一个可自定义长度的泛型数组
aryInit (test, NUM) ; //初始化该数组对象,长度为NUM
printf ("Input %d data of int:\n", NUM) ;
for (i = 0; i < test.arySize; i++)
scanf ("%d", &test.varAry[i]) ; //逐一存入数据到数组中去
printf ("type int:\n") ;
for (i = 0; i < test.arySize; i++) //将数组中的元素逐一输出
{
if (!(i % 4) && i) printf ("\n") ;
printf ("%d\t", test.varAry[i]) ;
}
printf ("\n\n") ;
# include "AryEnd.h" //导入关闭宏的头文件
}
void showFloat ()
{
/*
* 运用VarArray.h中实现的可自定义长度的泛型数组来存储float型数据
*/
# define Ary_FLOAT //指定泛型数组的类型为float
# include "VarArray.h" //导入泛型数组的定义,并将数组类型确定为float
# undef Ary_FLOAT //关闭宏
int i ;
enum {NUM = 2} ; //用常量来指定数组的长度(长度为2)
VarArray test ; //实例化一个可自定义长度的泛型数组
aryInit (test, NUM) ; //初始化该数组对象,长度为NUM
printf ("Input %d data of float:\n", NUM) ;
for (i = 0; i < test.arySize; i++)
scanf ("%f", &test.varAry[i]) ; //逐一存入数据到数组中去
printf ("type float:\n") ;
for (i = 0; i < test.arySize; i++) //将数组中的元素逐一输出
{
if (!(i % 4) && i) printf ("\n") ;
printf ("%f\t", test.varAry[i]) ;
}
printf ("\n\n") ;
# include "AryEnd.h" //导入关闭宏的头文件
}
void showChar ()
{
/*
* 运用VarArray.h中实现的可自定义长度的泛型数组来存储char型数据
*/
# define Ary_CHAR //指定泛型数组的类型为char
# include "VarArray.h" //导入泛型数组的定义,并将数组类型确定为char
# undef Ary_CHAR //关闭宏
int i ;
enum {NUM = 2} ; //用常量来指定数组的长度(长度为2)
VarArray test ; //实例化一个可自定义长度的泛型数组
aryInit (test, NUM) ; //初始化该数组对象,长度为NUM
printf ("Input %d data of char:\n", NUM) ;
for (i = 0; i < test.arySize; i++)
scanf ("%c", &test.varAry[i]) ; //逐一存入数据到数组中去
printf ("type char:\n") ;
for (i = 0; i < test.arySize; i++) //将数组中的元素逐一输出
{
if (!(i % 4) && i) printf ("\n") ;
printf ("%c\t", test.varAry[i]) ;
}
printf ("\n\n") ;
# include "AryEnd.h" //导入关闭宏的头文件
}
int main (int argc, char **argv)
{
showInt () ; // 运用可自定义长度的泛型数组来存储int型数据,并输出
while (getchar () != '\n') ;
showFloat () ; // 运用可自定义长度的泛型数组来存储float型数据,并输出
while (getchar () != '\n') ;
showChar () ; // 运用可自定义长度的泛型数组来存储char型数据,并输出
return 0 ;
}
----@Author CLinHF