t.i
gcc -g -S printtest.i -o printtest.s
printtest.i:$(SRC)
gcc -g -E $(SRC) -o printtest.i
clean:
rm *~ *.o *.s *.i $(TARGET)
*此处为了观察代码的编译、汇编、链接过程,Makefile稍显复杂,可直接用下述指令编译
[html] view plaincopyprint gcc printtest.c -o printtest
gcc printtest.c -o printtest
【运行结果】
[html]
**************** Integer Test ****************
0123456789
**************** Integer Test ****************
0123456789
**************** Float Test ****************
2.600000
**************** String Test ****************
Generics test!
**************** Integer Test ****************
0123456789
**************** Integer Test ****************
0123456789
**************** Float Test ****************
2.600000
**************** String Test ****************
Generics test!
上述代码,有一处值得注意,在定义时,提供了两种print_int函数:
[html]
static int print_int(void *data)
{
printf("%d", (int)data);
return RET_OK;
}
static int print_int2(void *data)
{
printf("%d", *(int*)data);
return RET_OK;
}
static int print_int(void *data)
{
printf("%d", (int)data);
return RET_OK;
}
static int print_int2(void *data)
{
printf("%d", *(int*)data);
return RET_OK;
}调用时:
[html]
int i = 0;
int *pi = &i;
PRINTSTAT( "%s", "Integer")
for(; i<10; i++)
print(print_int, (void *)i);
printf("\n");
PRINTSTAT( "%s", "Integer")
for(i = 0; i<10; i++)
print(print_int2, (void *)pi);
printf("\n");
int i = 0;
int *pi = &i;
PRINTSTAT( "%s", "Integer")
for(; i<10; i++)
print(print_int, (void *)i);
printf("\n");
PRINTSTAT( "%s", "Integer")
for(i = 0; i<10; i++)
print(print_int2, (void *)pi);
printf("\n");
调用print_int时,将int类型强制转换为void *类型;调用print_int2时,将int *类型强制转化为void *类型。令人惊讶的是,上述两种方法,都能输出正确结果。其实,print_int提供的方法只是凑巧而已,因为int是4字节,而void *类型也是4字节,强制转换居然没有发生错误!但如果是float类型,再利用print_int类似的方法就不行了,gcc提示无法进行转换。安全的方式是将int *转换为void *,再在print_int处理函数中将void *转换为int *,然后解引用。
2 采用“#”
方法1提供的代码中,已经看出了“#”的威力。下面看看泛型的另一种实现:
【代码清单】
printtest.h
[html]
#ifndef __PRINTTEST_H__
#define __PRINTTEST_H__
#define GNERIC_PRINT(TYPE,FORMAT,SUFFIX) \
int print##SUFFIX( TYPE data )\
{\
printf(FORMAT, data);\
return 0;\
}
#endif
#ifndef __PRINTTEST_H__
#define __PRINTTEST_H__
#define GNERIC_PRINT(TYPE,FORMAT,SUFFIX) \
int print##SUFFIX( TYPE data )\
{\
printf(FORMAT, data);\
return 0;\
}
#endif
printtest.c
[html]
#include
#include
#include "printtest.h"
#define DEBUG 0
#define PRINTSTAT( FORMAT, STAT) \
printf("**************** " FORMAT " Test ****************\n"\
,STAT);
#define DEBUG_PRINT(FORMAT, VALUE) printf("File %s line %d: "\
#VALUE " = " FORMAT "\n"\
,__FILE__, __LINE__,VALUE\
);
enum {
RET_OK,
RET_FAIL
};
GNERIC_PRINT(int, "%d", _int)
GNERIC_PRINT(float, "%f", _float)
GNERIC_PRINT(char *, "%s", _str)
int main(void)
{
int i = 0;
float f = 2.6;
char *test = "Generics test!";
#if DEBUG
DEBUG_PRINT("%f", f)
#endif
PRINTSTAT( "%s", "Integer")
for(; i<10; i++)
print_int(i);
printf("\n");
PRINTSTAT( "%s", "Float")
print_float(f);
printf("\n");
PRINTSTAT( "%s", "String")
print_str(test);
printf("\n");
return RET_OK;
}
#include
#include
#include "printtest.h"
#define DEBUG 0
#define PRINTSTAT( FORMAT, STAT) \
printf("**************** " FORMAT " Test ****************\n"\
,STAT);
#define DEBUG_PRINT(FORMAT, V