posted Mar 5, 2009, 5:28 AM by Unknown user
#include <stdarg.h>
int foo(char *fmt, ...) { va_list ap; int d; int count=0; char c, *p, *s;
va_start(ap, fmt); while (*fmt) switch(*fmt++) { case '%': if((*fmt) && (*(fmt) != '%')) count++; else if (*fmt) fmt++; break; } va_end(ap); printf("%d", count);
va_start(ap, fmt); va_end(ap);
return count; }
int dup(char *v, ...) { va_list ap; int d; int count=0; char c, *s;
va_start(ap, v); va_end(ap);
} int main() { char *p = "%d%s%d"; foo(p); dup(p); }
|
posted Jan 22, 2009, 7:43 PM by Unknown user
[
updated Jan 22, 2009, 7:47 PM
]
Objective-C는 컴파일러가 생성하는 객체의 구조에 접근 가능하게 하는 API를 제공한다. 이를
이용하면 GNU Objective-C의 Object나 MacOS X의 NSObject같은 최상위 클래스를 쉽게 작성할 수 있다.
반드시 그렇게 해야 할 이유는 없지만 말이다.
API를 사용하려면 다음의 파일들을 #include 해야 한다.
- objc/objc.h
- objc/objc-api.h
- objc/objc-class.h (MacOS X)
Objective-C가 생성하는 모든 객체들은 헤더 부분에 클래스 객체에 대한 포인터를 가지며, 데이터 부분은 클래스 정의에 따라 달라지게 된다. 객체의 헤더 부분은 struct objc_object에 정의 되어 있다.
/* GNU Objective-C - objc/objc.h */
struct objc_object { struct objc_class* class_pointer; };
MacOS X에서는 class_pointer대신 isa라는 이름이 사용된다.
struct objc_class는 클래스 객체의 구조를 정의한다. 클래스 역시 객체이므로
메타클래스라고 하는 자신의 클래스 객체에 대한 포인터를 가지며, 크기, 이름, 부모 클래스등 생성할 객체에 대한 여러 가지
정보를 담고 있다.
/* GNU Objective-C - objc/objc.h */ struct objc_class { struct objc_class* class_pointer; struct objc_class* super_class; const char* name; long version; unsigned long info; long instance_size; struct objc_ivar_list* ivars; struct objc_method_list* methods; struct sarray* dtable; struct objc_class* subclass_list; struct objc_class* sibling_class; struct objc_protocol_list *protocols; void* gc_object_type; };
최상위 클래스는 클래스 포인터를 초기화 하고 객체의 생성과 소멸을 담당하는 메서드들을 제공해야 한다. GNU Objective-C의 Object처럼 alloc, init, free, new를 작성해보자.
/* Object.h */ #include <objc/objc.h> #include <objc/objc-api.h> #ifdef __APPLE__ #include <objc/objc-class.h> #endif @interface Object { struct objc_class* isa; } + (id) alloc; + (id) new; - (id) init; - (void) free; @end
- isa - 클래스 포인터
- alloc - 객체가 필요한 메모리 공간을 할당한다.
- free - 객체가 사용한 메모리 공간을 해제한다.
- init - 객체를 초기화 한다.
- new - [[object alloc] init]
alloc를 제외한 나머지는 다음과 같이 간단하게 구현될 수 있다.
/* Object.m */ #include "Object.m" #include <stdlib.h> @implementation Object + (id) alloc { return alloc_object (self); } + (id) new { id obj = [self alloc]; if (obj == nil) return nil; return [obj init]; } - (id) init { return self; } - (void) free { if (self != nil) free (self); } @end 객체가 필요한 공간을 할당하려면 객체의 크기를 알아야 한다. 객체의 크기는 클래스의 instance_size 필드에 저장이 되는데, 실제 필요한 크기는 여기에 헤더부분(클래스포인터)의 크기를 포함해야 한다.
/* Object.m */ static struct objc_object* alloc_object (struct objc_class* class) { size_t size; struct objc_object* obj; /* 객체가 필요로 하는 공간의 크기 */ size = sizeof(struct objc_object) + class->instance_size; /* 공간을 할당한다 */ obj = (struct objc_object*)calloc(1, size); if (obj == NULL) return nil; /* MacOS X는 class_pointer대신 isa라는 이름을 사용하므로 #ifdef로 처리한다 */ #ifdef __APPLE__ obj->isa = class; #else obj->class_pointer = class; #endif return obj; }
MacOS X는 추가적으로 forward:sel:메서드를 필요로 한다.
#ifdef __APPLE__ - (id) forward: (SEL)sel: (marg_list)args { return self; } #endif
이제 위에서 만든 최상위 클래스를 사용해 보도록 하자.
#include "Object.h" #include <stdio.h> @interface Child: Object { int a; } - (id) init; - (void) print; @end @implementation Child - (id) init { [super init]; a = 2871; return self; } - (void) print { printf ("a = %d\n", a); } @end int main () { id t; t = [[Child alloc] init]; /* 개체를 생성하고 초기화 한다 */ [t print]; /* print메시지를 보낸다 */ [t free]; /* 개체를 없앤다 */ return 0; }
|
posted May 25, 2008, 2:48 AM by Unknown user
[
updated Feb 16, 2009, 7:15 PM
]
[ Top ] [ Samples ]
DESCRIPTION
This program demonstrates how to use qse_awk_rtx_call().
SOURCE
7 #include <qse/awk/awk.h> 8 #include <qse/utl/stdio.h> 9 10 static const qse_char_t* src = QSE_T( 11 "function init() { a = 20; }" 12 "function main() { a++; }" 13 "function fini() { print a; }" 14 ); 15 16 static const qse_char_t* f[] = 17 { 18 QSE_T("init"), 19 QSE_T("main"), 20 QSE_T("main"), 21 QSE_T("main"), 22 QSE_T("main"), 23 QSE_T("fini"), 24 }; 25 26 int main () 27 { 28 qse_awk_t* awk = QSE_NULL; 29 qse_awk_rtx_t* rtx = QSE_NULL; 30 int ret, i; 31 32 /* create a main processor */ 33 awk = qse_awk_opensimple (); 34 if (awk == QSE_NULL) 35 { 36 qse_fprintf (QSE_STDERR, QSE_T("error: cannot open awk\n")); 37 ret = -1; goto oops; 38 } 39 40 /* don't allow BEGIN, END, pattern-action blocks */ 41 qse_awk_setoption (awk, qse_awk_getoption(awk) & ~QSE_AWK_PABLOCK); 42 43 ret = qse_awk_parsesimple ( 44 awk, 45 QSE_AWK_PARSE_STRING, src, /* parse AWK source in a string */ 46 QSE_NULL /* no parse output */ 47 ); 48 if (ret == -1) 49 { 50 qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"), 51 qse_awk_geterrmsg(awk)); 52 goto oops; 53 } 54 55 /* create a runtime context */ 56 rtx = qse_awk_rtx_opensimple ( 57 awk, 58 QSE_NULL /* no console files */ 59 ); 60 if (rtx == QSE_NULL) 61 { 62 qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"), 63 qse_awk_geterrmsg(awk)); 64 ret = -1; goto oops; 65 } 66 67 /* invoke functions as indicated in the array f */ 68 for (i = 0; i < QSE_COUNTOF(f); i++) 69 { 70 ret = qse_awk_rtx_call (rtx, f[i], QSE_NULL, 0); 71 if (ret == -1) 72 { 73 qse_fprintf (QSE_STDERR, QSE_T("%d error: %s\n"), 74 i, qse_awk_rtx_geterrmsg(rtx)); 75 goto oops; 76 } 77 } 78 79 oops: 80 /* destroy a runtime context */ 81 if (rtx != QSE_NULL) qse_awk_rtx_close (rtx); 82 /* destroy the processor */ 83 if (awk != QSE_NULL) qse_awk_close (awk); 84 return ret; 85 }
|
|