C에서 구조를 동적으로 정의할 수 있습니까?
저는 이것이 정말 명백한 질문으로 끝날 것이라고 확신합니다. 그래서 저는 그것에 대한 많은 정보를 찾지 못했습니다.그래도 물어볼 가치가 있다고 생각했어요 :)
기본적으로 구조를 사용하여 데이터에 접근하는 것은 매우 빠릅니다.데이터가 네트워크에서 구조물로 즉시 처리될 수 있는 형태로 나온다면 성능 측면에서 보면 상당히 좋은 결과입니다.
그러나 구조를 동적으로 정의하는 것이 가능합니까?클라이언트와 서버 앱이 데이터 스트림의 형식을 협상한 다음 이 정의를 구조로 사용할 수 있습니까?
그렇지 않다면 더 좋은 방법이 있습니까?
다들 감사합니다.
컴파일 시간 구조와 동일한 구조를 동적으로 정의할 수 없습니다.
구조물과 동등한 정보를 포함할 수 있는 동적 구조물을 만드는 것은 가능하지만 어려운 일입니다.데이터에 대한 액세스는 컴파일 타임에 사용할 수 있는 것보다 덜 편리합니다.
그 외에는 구성원에 액세스할 수 없습니다.somestruct.not_seen_at_compile_time
점을 이용하여.
또는 화살표->
컴파일 타임에 정의되지 않은 경우의 표기법.
네트워크 통신의 경우, 해결해야 할 다른 문제들이 있는데, 특히 '내성'이 그것입니다.즉, 와이어의 데이터에는 멀티바이트(2, 4, 8) 정수가 포함될 수 있으며 MSB 또는 LSB 중 하나가 먼저 전송되지만, 하나의 머신이 리틀 엔디안(IA-32, IA-64, x86/64)이고 다른 머신이 빅 엔디안(SPARC, PPC, Intel이 아닌 거의 모든 것)인 경우 데이터를 변환해야 합니다.부동 소수점 형식도 문제가 될 수 있습니다.네트워크를 통해 데이터를 전송하는 방법을 정의하는 데 전념하는 수많은 표준이 있습니다. 이는 사소한 것이 아닙니다.IP, TCP, UDP 등 특정한 것도 있고 ASN.1 등 일반적인 것도 있습니다.
그러나 '동적인 데이터 구조를 할 수 없다'는 부분은 사물을 제한합니다. 즉, 데이터 구조가 무엇인지, 데이터 구조를 어떻게 해석할 것인지에 대해 사전에 동의해야 합니다.
어떻게 하죠?
gerty3000은 다음과 같이 묻습니다.
구조물과 동등한 정보를 포함할 수 있는 동적 구조물을 만드는 것은 가능하지만 어려운 일입니다.— 어떻게 하죠?컴파일러에서 구조 메모리 레이아웃 루틴을 복제할 필요 없이 동적으로 정의된 구조를 다른 C 코드(동일한 컴파일러 및 기타 설정을 가정)로 전달하고 싶습니다.프로세스 내부에서 이러한 구조의 필드에 액세스하는 일은 별로 없을 것이므로(단 한 번만 초기화) 편리한 구문은 문제가 되지 않습니다.
메모리 레이아웃을 어떤 형태로든 복제하지 않으면 할 수 없습니다.꼭 똑같을 필요는 없겠지만, 같다면 최선일 것입니다.대략적인 방법을 보여주는 샘플 코드가 있습니다.
dynstruct.c
여기에는 기본 구조물 조작 재료인 구조물과 (단순) 부재를 설명하기 위한 구조물이 포함되어 있습니다.문자열이 아닌 전체 어레이를 처리하려면 더 많은 작업이 필요하며, 다른 유형에 대해서도 많은 작업을 수행해야 합니다.
그것은 또한 포함하고 있습니다.main()
코드를 테스트하는 프로그램입니다.에 전화를 걸었습니다.other_function()
, 데이터 구조에서 정의한 구조가 구조와 정확히 일치한다는 것을 보여줍니다.이 데이터는 64비트 시스템을 가정하고 있습니다.double
8바이트 경계에 정렬해야 합니다.(구조에 4바이트 홀이 있음). 다음과 같은 컴퓨터에 대해 데이터를 조정해야 합니다.double
4바이트 경계에 있을 수 있습니다.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* This is the type that will be simulated dynamically */
/*
struct simulated
{
int number;
double value;
char string[32];
};
*/
/* SOF structure.h */
typedef enum Type { INT, DOUBLE, STRING } Type;
typedef struct Descriptor
{
size_t offset;
Type type;
size_t type_size;
size_t array_dim;
char name[32];
} Descriptor;
typedef struct Structure
{
size_t size;
char name[32];
Descriptor *details;
} Structure;
extern void *allocate_structure(const Structure *structure);
extern void deallocate_structure(void *structure);
extern void *pointer_to_element(void *p, const Descriptor *d);
extern int get_int_element(void *p, const Descriptor *d);
extern void set_int_element(void *p, const Descriptor *d, int newval);
extern double get_double_element(void *p, const Descriptor *d);
extern void set_double_element(void *p, const Descriptor *d, double newval);
extern char *get_string_element(void *p, const Descriptor *d);
extern void set_string_element(void *p, const Descriptor *d, char *newval);
/* EOF structure.h */
static Descriptor details[] =
{
{ 0, INT, sizeof(int), 1, "number" },
{ 8, DOUBLE, sizeof(double), 1, "value" },
{ 16, STRING, sizeof(char), 32, "string" },
};
static Structure simulated = { 48, "simulated", details };
void *allocate_structure(const Structure *structure)
{
void *p = calloc(1, structure->size);
return p;
}
void deallocate_structure(void *structure)
{
free(structure);
}
void *pointer_to_element(void *p, const Descriptor *d)
{
void *data = (char *)p + d->offset;
return data;
}
int get_int_element(void *p, const Descriptor *d)
{
assert(d->type == INT);
int *v = pointer_to_element(p, d);
return *v;
}
void set_int_element(void *p, const Descriptor *d, int newval)
{
assert(d->type == INT);
int *v = pointer_to_element(p, d);
*v = newval;
}
double get_double_element(void *p, const Descriptor *d)
{
assert(d->type == DOUBLE);
double *v = pointer_to_element(p, d);
return *v;
}
void set_double_element(void *p, const Descriptor *d, double newval)
{
assert(d->type == DOUBLE);
double *v = pointer_to_element(p, d);
*v = newval;
}
char *get_string_element(void *p, const Descriptor *d)
{
assert(d->type == STRING);
char *v = pointer_to_element(p, d);
return v;
}
void set_string_element(void *p, const Descriptor *d, char *newval)
{
assert(d->type == STRING);
assert(d->array_dim > 1);
size_t len = strlen(newval);
if (len > d->array_dim)
len = d->array_dim - 1;
char *v = pointer_to_element(p, d);
memmove(v, newval, len);
v[len] = '\0';
}
extern void other_function(void *p);
int main(void)
{
void *sp = allocate_structure(&simulated);
if (sp != 0)
{
set_int_element(sp, &simulated.details[0], 37);
set_double_element(sp, &simulated.details[1], 3.14159);
set_string_element(sp, &simulated.details[2], "Absolute nonsense");
printf("Main (before):\n");
printf("Integer: %d\n", get_int_element(sp, &simulated.details[0]));
printf("Double: %f\n", get_double_element(sp, &simulated.details[1]));
printf("String: %s\n", get_string_element(sp, &simulated.details[2]));
other_function(sp);
printf("Main (after):\n");
printf("Integer: %d\n", get_int_element(sp, &simulated.details[0]));
printf("Double: %f\n", get_double_element(sp, &simulated.details[1]));
printf("String: %s\n", get_string_element(sp, &simulated.details[2]));
deallocate_structure(sp);
}
return 0;
}
기타.
이 코드는 구조 설명 자료에 대해 아무것도 모릅니다.dynstruct.c
; 그것은 그것에 대해서 알고 있습니다.struct simulated
시뮬레이션 코드가 시뮬레이션 할 수 있습니다.전달받은 데이터를 출력하고 수정합니다.
#include <stdio.h>
#include <string.h>
extern void other_function(void *p);
struct simulated
{
int number;
double value;
char string[32];
};
void other_function(void *p)
{
struct simulated *s = (struct simulated *)p;
printf("Other function:\n");
printf("Integer: %d\n", s->number);
printf("Double: %f\n", s->value);
printf("String: %s\n", s->string);
s->number *= 2;
s->value /= 2;
strcpy(s->string, "Codswallop");
}
샘플출력
Main (before):
Integer: 37
Double: 3.141590
String: Absolute nonsense
Other function:
Integer: 37
Double: 3.141590
String: Absolute nonsense
Main (after):
Integer: 74
Double: 1.570795
String: Codswallop
분명히 이 코드는 생산 준비가 되지 않았습니다.그것은 무엇을 할 수 있는지를 충분히 보여주는 것입니다.처리해야 할 문제 중 하나는Structure
그리고.Descriptor
데이터가 정확합니다.그런 종류의 코드에 너무 많은 주장을 넣을 수는 없습니다.예를 들어, 나는 정말로 해야 합니다.assert(d->size == sizeof(double);
인에get_double_element()
. 또한 다음을 포함하는 것이 현명할 것입니다.assert(d->offset % sizeof(double) == 0);
확실하게 하기 위해double
요소가 적절하게 정렬되어 있습니다.아니면 당신은.validate_structure(const Structure *sp);
이 모든 유효성 검사를 수행한 함수입니다.당신은 기능이 필요할 것입니다.void dump_structure(FILE *fp, const char *tag, const Structure *sp);
태그 앞에 지정된 파일에 정의된 구조를 덤프하여 디버깅을 지원합니다.기타.
이 코드는 순수한 C입니다. C++ 컴파일러에서는 C++로 컴파일할 수 없습니다.C++ 컴파일러를 만족시키기에는 캐스트가 부족합니다.
아닙니다. 컴파일 시 모든 데이터 유형을 알아야 합니다.그것이 바로 그것을 "정말 빠르게" 만드는 것입니다.
또 다른 이론적 가능성은 libtcc와 같은 컴파일러 라이브러리를 사용하여 런타임에 일부 코드를 컴파일하는 것입니다.
이론적으로 매우 매력적이지만(자체 수정 애플리케이션처럼 들리지만), 애플리케이션은 구조를 위한 C 코드를 생성하여 템플릿에 삽입한 다음 libtcc에 컴파일을 요청하고 템플릿에 정의된 일부 함수를 호출하여 구조를 사용하면 됩니다), 이 솔루션은 실제로는 효과가 크지 않을 것입니다.왜 그럴까요? 음, 2016년 현재 libtcc(그리고 전체 tcc 프로젝트)는 매우 활발하게 개발되지 않았고 x86_64와 같은 아키텍처에 문제가 있습니다.
동적 구조의 경우 답은 아니오입니다.
어떤 데이터가 들어오는지 알고 있다면 C++에서는 오버로드된 << inoperator>를 사용하여 스트림에서 데이터를 읽을 수 있습니다.
C에서는 데이터가 들어오는 길이를 알고 sscanf와 같은 함수를 사용하면 데이터를 읽을 수 있다고 가정하고 스트림을 문자열로 변환할 수 있습니다.
소스 수준 구조를 정의할 수는 없지만, 데이터 구조를 설정하여 통신할 데이터의 각 필드별로 이름/태그와 오프셋을 저장한 다음 그에 따라 올바른 오프셋으로 데이터를 저장/읽기할 수 있습니다.모든 유형을 다음 값의 배수인 경계에 정렬해야 합니다.sizeof(type)
휴대용으로물론, 클라이언트와 서버가 동일한 데이터 표현(내성 및 기타 고려 사항)을 가지고 있고 직접 액세스 성능이 정말 필요한 경우가 아니라면 대신 적절한 직렬화 및 병렬화 루틴을 작성할 것입니다.
gerty3000의 답변을 바탕으로 도서관을 만들었습니다.저는 최종 사용자에게서 무언가를 추상화했습니다.힘들었지만 결국은 효과가 있었습니다.개선할 점이 있다면 제안을 받을 수 있습니다.여기 코드가 있습니다.
type-machine.h // 유형 및 함수 프로토타입 정의
#ifndef TYPE_MACHINE_H
#define TYPE_MACHINE_H
#ifdef __cplusplus
extern "C" {
#endif
#define B8 char
#define B8U unsigned char
#define B16 short
#define B16U unsigned short
#define B32 int
#define B32U unsigned int
#define B64 long long int
#define B64U unsigned long long int
#define BP32 float
#define BP64 double
#define BIT_ON(var,bit) ((var)=((var) | (bit)))
#define BIT_OFF(var,bit) ((var)=((var) & (~bit)))
#define BIT_IS_ON(var,bit) (var & bit)
#define PAIR(position,value) ((value)=((position) << (1)))
typedef struct Bit8Tag BIT;
typedef enum {
Off, On
} STATUS;
typedef enum {
B8_T, B8U_T, B16_T, B16U_T, B32_T, B64_T, B64U_T, B32U_T, BP32_T, BP64_T
} TYPE;
typedef struct ClassFieldTag ClassField;
typedef struct ClassTag Class;
typedef enum {
CLASS_SIZE, CLASS_INSERT, CLASS_SHOW
} CLASS_MODE;
#if (defined(WIN32) || defined(WINDOWS_XP))
#define is_win()(1)
#else
#define is_win()(0)
#define TYPE_CALL
#define TYPE_TYPE
#endif // WIN32
#include <math.h>
#include <string.h>
#include <assert.h>
#define area(a,b) ((a)*(b))
#define radian(x,y)(atan2(y,x))
#define angle(a)( (a * (180 / M_PI)) + 180)
#if defined WIN32
#define ARIAL_PATH "C:/Windows/Fonts/arial.ttf\0"
#else
#define ARIAL_PATH "home/media/TheGreat/\0"
#endif
struct ClassFieldTag {
TYPE type;
size_t mem, size, len;
B8 name[32];
struct ClassFieldTag * next, *preview;
};
extern ClassField * class_set_push();
extern ClassField * class_field_set(ClassField * set, TYPE type, B8 * name, size_t len, size_t mem);
extern STATUS class_set_next_back(ClassField ** set, ClassField * next);
extern STATUS class_set_next_front(ClassField ** set, ClassField * next);
extern STATUS class_insert_back(Class * set, TYPE type, B8 * name, size_t len);
extern STATUS class_insert_front(Class * set, TYPE type, B8 * name, size_t len);
struct ClassTag {
B8 name[32];
void * data;
B8 * String;
B16 Short;
B16U UShort;
B32 Int;
B32U UInt;
B64 Long;
B64 ULong;
BP32 Float;
BP64 Double;
ClassField * field;
};
Class * class_push(B8 name[32]);
extern STATUS class_zero(Class * set, B8 name[32]);
extern void class_data_push(Class * set);
extern void class_data_pop(Class * set);
extern void * class_set_to(Class * set, ClassField * field);
extern void class_int_set(Class * set, ClassField * field, B32 value);
extern B32 class_int_get(Class * set, ClassField * field);
extern void class_double_set(Class * set, ClassField * field, BP64 value);
extern BP64 class_double_get(Class * set, ClassField * field);
extern void class_string_set(Class * set, ClassField * field, B8 * value);
extern B8 * class_string_get(Class * set, ClassField * field);
extern void class_mode(Class * set, ClassField * field, CLASS_MODE mode);
extern void class_field_pop(Class * set);
extern void class_pop(Class * set);
extern STATUS class_ex(Class * mine);
struct Bit8Tag {
unsigned b16 : 16;
};
extern void bit_on(BIT * value, int bit);
extern void bit_off(BIT * value, int bit);
extern STATUS bit_is_on(BIT value, int bit);
extern B32U strsub(B8 * data, B8 * key);
#ifdef __cplusplus
}
#endif
#endif // TYPE_MACHINE_H
type-machine.c // 이 기능을 선언합니다.
#include <Place/include/type-machine.h>
#include <malloc.h>
#include <stdio.h>
Class * class_push(B8 name[32]) {
Class * set = (Class *) malloc(sizeof (Class));
if(class_zero(set,name)){
return(set);
}
return(NULL);
}
void class_data_push(Class * set) {
B32 class_size = sizeof (Class), class_field_size = sizeof (ClassField);
if (set) {
if (class_size < sizeof (set))class_size = sizeof (set);
if (class_field_size < sizeof (set->field))class_field_size = sizeof (set->field);
}
set->data = malloc(class_size + class_field_size + 1);
}
void class_data_pop(Class * set) {
if (set && set->data) {
free(set->data);
}
}
void * class_set_to(Class * set, ClassField * field) {
if (set && set->data && field) {
void * data = (char *) set->data + field->mem;
return data;
}
return (NULL);
}
void class_int_set(Class * set, ClassField * field, B32 value) {
if (set) {
assert(field->type == B32_T);
B32 * update = class_set_to(set, field);
*update = value;
}
}
B32 class_int_get(Class * set, ClassField * field) {
if (set) {
assert(field->type == B32_T);
B32 * data = class_set_to(set, field);
return (*data);
}
return (0);
}
void class_double_set(Class * set, ClassField * field, BP64 value) {
if (set) {
assert(field->type == BP64_T);
BP64 * update = class_set_to(set, field);
*update = value;
}
}
BP64 class_double_get(Class * set, ClassField * field) {
if (set) {
assert(field->type == BP64_T);
BP64 * data = class_set_to(set, field);
return (*data);
}
return (0);
}
void class_string_set(Class * set, ClassField * field, B8 * value) {
if (set && field && field->len > 1 && value) {
assert(field->type == B8_T);
size_t len = strlen(value);
if (len < 2) {
len = 2;
}
if (len > field->len)len = field->len - 1;
B8 * buffer = class_set_to(set, field);
if (buffer) {
memmove(buffer, value, len);
buffer[len] = '\0';
}
}
}
B8 * class_string_get(Class * set, ClassField * field) {
if (set && field) {
assert(field->type == B8_T);
B8 * data = class_set_to(set, field);
return (data);
}
return (NULL);
}
STATUS class_zero(Class * set, B8 * name) {
if (set) {
set->String = NULL;
set->Short = 0;
set->UShort = 0;
set->Int = 0;
set->UInt = 0;
set->Long = 0;
set->ULong = 0;
set->Float = 0;
set->Double = 0;
set->data = NULL;
memset(set->name, 0, sizeof (set->name));
if (name)memmove(set->name, name, strlen(name));
set->field = NULL;
return (On);
}
return (Off);
}
ClassField * class_set_push() {
return (malloc(sizeof (ClassField)));
}
void class_field_pop(Class * set) {
if (set) {
ClassField * field = set->field;
while (field) {
ClassField * next = field->next;
if (field) {
free(field);
field = NULL;
}
field = next;
}
}
}
void class_pop(Class * set) {
if (set) {
class_data_pop(set);
class_field_pop(set);
free(set);
set = NULL;
}
}
ClassField * class_field_set(ClassField * field, TYPE type, B8 * name, size_t len, size_t mem) {
if (field) {
size_t lenght = (name) ? strlen(name) : 0;
if (lenght > 32) {
lenght = 31;
}
memcpy(field->name, name, lenght);
field->name[lenght] = 0;
field->type = type;
field->mem = mem;
field->len = len;
class_mode(NULL, field, CLASS_SIZE);
field->next = NULL;
field->preview = NULL;
return (field);
}
return (NULL);
}
STATUS class_set_next_back(ClassField ** field, ClassField * next) {
if (next == NULL)return (Off);
next->next = *field;
if (*field != NULL) {
(*field)->preview = next;
}
*field = next;
return (On);
}
STATUS class_set_next_front(ClassField ** field, ClassField * next) {
if (next == NULL)return (Off);
if (*field != NULL) {
ClassField * update = *field, *preview = NULL;
while (update->next != NULL) {
preview = update;
update = update->next;
}
update->preview = preview;
update->next = next;
return (On);
}
*field = next;
return (On);
}
STATUS class_insert_back(Class * set, TYPE type, B8 * name, size_t len) {
if (class_set_next_back(&set->field, class_field_set(class_set_push(), type, name, len, 0))) {
ClassField * preview = set->field;
if (preview->next) {
preview->mem = preview->next->mem + preview->next->size;
}
return (On);
}
return (Off);
}
STATUS class_insert_front(Class * set, TYPE type, B8 * name, size_t len) {
ClassField * next = class_field_set(class_set_push(), type, name, len, 0);
if (class_set_next_front(&set->field, next)) {
ClassField * preview = set->field;
while (preview) {
if (preview->next) {
if (preview->next == next) {
next->mem = preview->mem + preview->size;
}
}
preview = preview->next;
}
return (On);
}
return (Off);
}
void class_mode(Class * set, ClassField * field, CLASS_MODE mode) {
if (field) {
switch (field->type) {
case B8_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: %s\n", field->name, class_string_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = field->len * sizeof (B8);
}
break;
case CLASS_INSERT:
{
class_string_set(set, field, set->String);
}
break;
}
}
break;
case B8U_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: %s\n", field->name, class_string_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = field->len * sizeof (B8U);
}
break;
case CLASS_INSERT:
{
class_string_set(set, field, set->String);
}
break;
}
}
break;
case B16_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%i]\n", field->name, class_int_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (B16);
}
break;
case CLASS_INSERT:
{
class_int_set(set, field, set->Int);
}
break;
}
}
break;
case B16U_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%i]\n", field->name, class_int_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (B16U);
}
break;
case CLASS_INSERT:
{
class_int_set(set, field, set->Int);
}
break;
}
}
break;
case B32_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: %i\n", field->name, class_int_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (B32);
}
break;
case CLASS_INSERT:
{
class_int_set(set, field, set->Int);
}
break;
}
}
break;
case B32U_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%i]\n", field->name, class_int_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (B32U);
}
break;
case CLASS_INSERT:
{
class_int_set(set, field, set->Int);
}
break;
}
}
break;
case B64_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%i]\n", field->name, class_int_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (B64);
}
break;
case CLASS_INSERT:
{
class_int_set(set, field, set->Int);
}
break;
}
}
break;
case B64U_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%i]\n", field->name, class_int_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (B64U);
}
break;
case CLASS_INSERT:
{
class_int_set(set, field, set->Int);
}
break;
}
}
break;
case BP32_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%lf]\n", field->name, class_double_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (BP32);
}
break;
case CLASS_INSERT:
{
class_double_set(set, field, set->Double);
}
break;
}
}
break;
case BP64_T:
{
switch (mode) {
case CLASS_SHOW:
{
printf("%s: [%lf]\n", field->name, class_double_get(set, field));
}
break;
case CLASS_SIZE:
{
field->size = sizeof (BP64);
}
break;
case CLASS_INSERT:
{
class_double_set(set, field, set->Double);
}
break;
}
}
break;
}
}
}
void bit_on(BIT * value, int bit) {
BIT_ON(value->b16, bit);
}
void bit_off(BIT * value, int bit) {
BIT_OFF(value->b16, bit);
}
STATUS bit_is_on(BIT value, int bit) {
if (value.b16 & bit)return (On);
return (Off);
}
B32U strsub(B8 * data, B8 * key) {
if (data && key) {
B8 *d = data;
B32U len = strlen(key), p = 0;
if (len > strlen(d))return (0);
while (*d != '\0') {
if (*(d + len) != '\0') {
B32U x = 0;
while (x <= len) {
if (key[x] == *d) {
*d++;
p++;
} else break;
x++;
}
if (x == len)return (p);
} else if (len == 1) {
if (*d == key[0])return (p);
}
p++;
*d++;
}
}
return (0);
}
main.c // testing...
#include "network.h"
#include <conio.h>
STATUS class_ex(Class * set) {
class_data_push(set);
if (set->data) {
ClassField * field = set->field;
while (field) {
if (!strcmp(field->name, "peso")) {
set->Double = 65.5;
}
if (!strcmp(field->name, "idade")) {
set->Int = 29;
}
if (!strcmp(field->name, "nome")) {
set->String = "Lisias de Castro Martins";
}
if (!strcmp(field->name, "endereco")) {
set->String = "Rua Mae D'Agua";
}
class_mode(set, field, CLASS_INSERT);
class_mode(set, field, CLASS_SHOW);
field = field->next;
}
return (On);
}
return (Off);
}
int main(int argc, char** argv) {
STATUS client_start = On;
if (client_start) {
Class * client = class_push("Client");;
class_insert_back(client, BP64_T, "peso", 1);
class_insert_back(client, B8_T, "endereco", 32);
class_insert_back(client, B32_T, "idade", 1);
class_insert_back(client, B8_T, "nome", 64);
printf("Classe[%s]\n\n", client->name);
if (class_ex(client)) {
}
class_pop(client);
getch();
}
return (EXIT_SUCCESS);
}
아직 짧은 더블과 다른 기능들을 구현해야 하는데 잘 되고 있습니다.
언급URL : https://stackoverflow.com/questions/6187908/is-it-possible-to-dynamically-define-a-struct-in-c
'it-source' 카테고리의 다른 글
Powershell get-event 로그 메시지 열이 너무 짧습니다. (0) | 2023.11.07 |
---|---|
코드 미러 편집기가 클릭할 때까지 콘텐츠를 로드하지 않습니다. (0) | 2023.11.07 |
mysql 명령줄의 디스플레이 설정을 조정하는 방법은? (0) | 2023.11.07 |
Oracle 왼쪽 외부 조인이 오른쪽 null 값을 표시하지 않음 (0) | 2023.11.07 |
ORA-01843: 유효한 달이 아님: TO_DATE('12-JUN-02', DD-MON-YY') (0) | 2023.11.07 |