C 와 범 형

[문제 설명] 범 형 은 특수 한 유형 으로 지정 한 유형의 작업 을 클 라 이언 트 코드 성명 과 예화 류 나 방법 으로 연기 합 니 다.범 형 은 함수 이름 충돌 문 제 를 해결 하 는 데 목적 을 둔다.일반적으로 범 형 은 고급 언어의 능력 이 라 고 생각 하고 범 형의 실현 은 보통 고급 언어의 템 플 릿 개념 을 빌린다.C 언어 는 범 형 을 실현 할 수 있 습 니까?답 은 할 수 있 지만 고급 언어 보다 훨씬 어렵다.다음은 두 가지 범 형의 실현 방법 을 총괄한다.
[해석]
컴 파일 환경:
Fedora 10, gcc 버 전 gcc 4.3.2
1 함수 포인터 로 범 형 실현
[코드 목록]
printtest.c
#include <stdio.h>
#include <stdlib.h>

#define DEBUG 0

#define PRINTSTAT( FORMAT, STAT) \
	printf("**************** " FORMAT " Test ****************
"\ ,STAT); #define DEBUG_PRINT(FORMAT, VALUE) printf("File %s line %d: "\ #VALUE " = " FORMAT "
"\ ,__FILE__, __LINE__,VALUE\ ); enum { RET_OK, RET_FAIL }; typedef int (*FXPrintFun)(void *data); int print(FXPrintFun _print, void *data) { return _print(data); } 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_float(void *data) { printf("%f", *(float*)data); return RET_OK; } static int print_str(void *data) { printf("%s", (char*)data); return RET_OK; } int main(void) { int i = 0; float f = 2.6; char *test = "Generics test!"; int *pi = &i; float *pf = &f; #if DEBUG DEBUG_PRINT("%f", f) #endif PRINTSTAT( "%s", "Integer") for(; i<10; i++) print(print_int, (void *)i); printf("
"); PRINTSTAT( "%s", "Integer") for(i = 0; i<10; i++) print(print_int2, (void *)pi); printf("
"); PRINTSTAT( "%s", "Float") print(print_float, (void *)pf); printf("
"); PRINTSTAT( "%s", "String") print(print_str, (void *)test); printf("
"); return RET_OK; }

Makefile
OBJS = printtest.o
TARGET = printtest
SRC = printtest.c

all:$(OBJS)
	gcc -g $(OBJS) -o $(TARGET)
$(OBJS):printtest.s
	gcc -g -c printtest.s -o $(OBJS)
printtest.s:printtest.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 은 약간 복잡 하 므 로 다음 명령 으로 컴 파일 할 수 있 습 니 다.
gcc printtest.c -o printtest

 
[운행 결과]
**************** Integer Test ****************
0123456789
**************** Integer Test ****************
0123456789
**************** Float Test ****************
2.600000
**************** String Test ****************
Generics test!

 
상기 코드 중 하 나 는 주의 할 점 이 있 습 니 다. 정의 할 때 두 가지 print 를 제공 합 니 다.int 함수:
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;
}

호출 시간:
int i = 0;

int *pi = &i;

PRINTSTAT( "%s", "Integer")
for(; i<10; i++)
	print(print_int, (void *)i);
printf("
"); PRINTSTAT( "%s", "Integer") for(i = 0; i<10; i++) print(print_int2, (void *)pi); printf("
");

print 호출int 시 int 형식 을 void * 형식 으로 강제 변환 합 니 다.print 호출int 2 시 int * 형식 을 void * 형식 으로 강제 전환 합 니 다.놀랍게도 상술 한 두 가지 방법 모두 정확 한 결 과 를 출력 할 수 있다.사실 printint 가 제공 하 는 방법 은 우연 일 뿐 입 니 다. int 는 4 바이트 이 고 void * 유형 도 4 바이트 이기 때문에 강제 변환 에 오류 가 발생 하지 않 았 습 니 다!하지만 플 로 트 타 입 이 라면 printint 와 유사 한 방법 은 안 됩 니 다. gcc 힌트 는 변환 할 수 없습니다.안전 한 방식 은 int * 를 void * 로 바 꾸 고 printint 처리 함수 에서 void * 를 int * 로 변환 한 다음 인용 을 풀 수 있 습 니 다.
 
2. '\ #' 을 사용한다.
방법 1 이 제공 하 는 코드 에는 '\ #' 의 위력 이 이미 보인다.다음은 범 형의 또 다른 실현 을 살 펴 보 자.
[코드 목록]
printtest.h
#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
#include <stdio.h>
#include <stdlib.h>
#include "printtest.h"

#define DEBUG 0

#define PRINTSTAT( FORMAT, STAT) \
	printf("**************** " FORMAT " Test ****************
"\ ,STAT); #define DEBUG_PRINT(FORMAT, VALUE) printf("File %s line %d: "\ #VALUE " = " FORMAT "
"\ ,__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("
"); PRINTSTAT( "%s", "Float") print_float(f); printf("
"); PRINTSTAT( "%s", "String") print_str(test); printf("
"); return RET_OK; }

Makefile
OBJS = printtest.o
TARGET = printtest
SRC = printtest.c

all:$(OBJS)
	gcc -g $(OBJS) -o $(TARGET)
$(OBJS):printtest.s
	gcc -g -c printtest.s -o $(OBJS)
printtest.s:printtest.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)

* SRC = printtest. c, SRC = printtest. c printtest. h 가 아 닙 니 다.후 자 는 예 처 리 를 정확하게 완성 하지 못 해 이해 하기 어렵다.이 유 를 설명 할 수 있 는 사람 이 있 습 니까?
채용
gcc printtest.h printtest.c -o printtest

 컴 파일 을 진행 하 다
 
[운행 결과]
**************** Integer Test ****************
0123456789
**************** Float Test ****************
2.600000
**************** String Test ****************
Generics test!

 
이런 방법 은 매우 멋 있어 보이 지만 코드 의 양 이 많은 상황 에서 실 수 를 하기 쉽다.따라서 함수 포인터 형식 으로 범 형 을 실현 하 는 것 을 추천 합 니 다. 
 
전재 는 출처 를 표시 하고 학습 교류 만 제공 하 며 상업 목적 에 사용 하지 마 십시오.
Copyright @ http://blog.csdn.net/tandesir
 
 
 
 
 
 
 
 

좋은 웹페이지 즐겨찾기