배경:
cpp의 for( auto it = arr.begin(); it != arr.end(); it++)
구문을 실현시키는 메크로를 만들었다. 근데 생각해보니 이거 list에 적용이 안되는 것 같고, 그렇다고 list 전용 메크로를 만들기에는 수고가 필요하니 list->arr를 만들기로 했다.
list의 각 요소를 저장하면서 동시에 list의 길이를 알아내서 arr의 공간을 계산하고 할당하는 것은 어려운 것 같다. 그리고 힙 공간을 사용한다면 에러 처리를 해야하고 이것은 복잡해지는 것 같다, 그러기에 좀 더 간소화하기 위해서 스텍을 이용하기로 했다. ( 근데 이게 맞나? )
//header
#define NULL ((void*)0)
typedef struct Node {
void* d;
struct Node* n;
} Node;
int list_to_array_function(void* list, void*** array, char** error_message);
간단하게 헤더를 만들었다.
일단 쓸 list의 구조를 만들었다. array는 즉석 제조 방식이고 그냥 const void* 형식의 array도 고려해본 결과 그냥 count 리턴, array는 참조 리턴을 하도록 정의했다.
// file
#include <malloc.h>
struct {
Node* list;
void** array;
char* message;
int size;
int count;
} list_to_array_function_struct = {
.message = "none",
};
#define self list_to_array_function_struct
#define call list_to_array_function_function
void list_to_array_function_function() {
if (!self.list) {
if (self.count != 0) {
self.array = calloc(self.count, sizeof(void*));
if (!self.array) self.message = "error_malloc", self.count = -1;
self.size = self.count;
}
return;
}
const void* d = self.list->d;
self.list = self.list->n;
self.count++;
call();
if (self.count <= 0) return;
self.array[--self.count] = d;
}
int list_to_array_function(void* list, void*** array, char** error_message) {
self.list = (Node*)list;
call();
if(error_message) *error_message = self.message;
self.message = "none";
*array = self.array;
return self.size;
}
#undef call
#undef self
void function() 형태로 주 함수를 구성하고 전역 변수를 이용하는 방식으로 만들었다. 이유는 C언어에서 함수는 인수까지 스텍을 쌓는 비효율적인 구조이기에, 본인은 스텍을 쌓을때 data만 쌓게 하고 싶었기 때문이다.
전역은 struct로, 따로 힙을 참조하는 포인터 형식이라면 한두번 쓸 함수의 목적에는 맞겠지만, 힙 영역의 에러처리가 귀찮아서 스텍 영역을 쓴다는 것을 고려해서 그냥 전역에 박았다.
꽤 간단한 구조다. 특히 cpp의 class 구조에서 더 적합한 구조인 것 같다.
// tast main
#include <stdio.h>
#define array_for(T, it, arr) for(T* it = arr.d; it != arr.d + arr.s; it++ )
int main(int argc, char** argv) {
Node head_data = { "_", NULL };
Node* head = &head_data;
Node* focus = head;
char* string = "hello world\n";
while (*string) {
focus->n = malloc(sizeof(Node));
focus = focus->n;
if (!focus) {
perror("error");
return -1;
}
focus->d = string;
focus->n = NULL;
string++;
}
struct {
void** d;
size_t s;
} array = {0};
array.s = list_to_array_function(head, &array.d, NULL);
array_for(void*, it, array) {
printf("%c", *(char*)*it);
}
free(array.d);
return 0;
}
만들었으니 테스트 해봤다.
그리고 느꼈다. list 어떻게 만들더라?
대가리가 깨진채 만들어서 그런가
대충 작동하니 좋았스
이전 것들은 전부 폰이라서 여기에 올린 것 중에 기념비적이고 유일무이하며 아마도 처음이자 마지막인 컴퓨터로 작업한 코드일듯