C Programming, A Modern Approach - K.N.KING์ผ๋ก C์ธ์ด๋ฅผ ๊ณต๋ถํ๋ฉด์ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค.
๊ณ ์ ๋ ์ฌ์ด์ฆ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ด์ฉํ ๊ฒฝ์ฐ ํ๋ก๊ทธ๋จ์ ์์ ํ๊ณ , ๋ค์ ์ปดํ์ผํ์ง ์๊ณ ๋ size๋ฅผ ๋ณ๊ฒฝํ ์๊ฐ ์๋ค.
๋ฐ๋ผ์ C๋ ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น(Dynamic Storage Allocation) ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ์ด๋ ์คํ ์๊ฐ๋์ ์ฌ์ฉํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น๋ฐ๋ ๊ฒ์ ๋งํ๋ค.
๐ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ํจ์๋ค
๋ณดํต malloc์ด ๊ฐ์ฅ ๋ง์ด ์ฐ์ธ๋ค.
์ด๋ค ํ์ ์ด ํ ๋น๋ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ํจ์๋ void* ํ์์ ๋ฐํํ๋ค. void*์ ์ด๋ค ํ์ ์ผ๋ก๋ ๋ณ์ ์ด ๊ฐ๋ฅํ๋ค.
๋์ ํ ๋น ํจ์๋ฅผ ํธ์ถํ ๋, ๊ทธ๋งํผ ์ถฉ๋ถํ ๊ณต๊ฐ์ด ๋จ์์์ง ์์ ๊ฐ๋ฅ์ฑ์ด ์๋ค. ๊ทธ๋ผ ํจ์๋ null pointer๋ฅผ ๋ฐํํ๋ค.
null pointer๋ ์๋ฌด๊ฒ๋ ๊ฐ๋ฆฌํค์ง ์๋ ํฌ์ธํฐ์ด๋ค. ๋ฐ๋ผ์ ํจ์์ ๋ฐํ๊ฐ์ ํฌ์ธํฐ ๋ณ์์ ์ ์ฅํ ํ์ ๋ฐ๋์ null pointer์ธ์ง ๊ฒ์ฌ๋ฅผ ํด์ฃผ์ด์ผ ํ๋ค.
null pointer๋ ๋งคํฌ๋ก์ ์ํด NULL๋ก ์ ์ธ๋์ด์๋ค. ๋ณดํต #include <stdlib.h>๋ฅผ ์ด์ฉํ๋ค.
๋ฐ๋ผ์ malloc์ ๋ฐํ ๊ฐ์ ์๋์ ๊ฐ์ด ํ
์คํธํ ์ ์๋ค.
p = malloc(10000);
if (p == NULL) {
/* allocation failed */
}
p == NULL์ด๋ผ๊ณ ์ฐ๋ ๋์
if (!p) ... ๋ ๊ฐ๋ฅํ๋ค.
(๋์ ํ ๋น๋ ๋ฌธ์์ด)
๐ malloc ํจ์
void *malloc(size_t size);
malloc์ size๋งํผ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ณ ํฌ์ธํฐ๋ฅผ ๋ฐํํ๋ค.
char์ size๋ 1์ด๊ธฐ ๋๋ฌธ์ malloc์ ์ด์ฉํ์ฌ ๋ฌธ์์ด ํจ์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ ๊ฒ์ ์ฝ๋ค.
๐ ๋ฌธ์์ด ํจ์์ n๊ฐ์ ๋ฌธ์๋ฅผ ์ ์ฅํ ๊ณต๊ฐ ํ ๋นํ๊ธฐ
p = malloc(n+1);
๊ทธ๋ผ ํ ๋น์ ํ ๋ p๋ char* ์ด ๋๋ค.
๋ ๋ฌธ์์ด์ด ์ฃผ์ด์ก์ ๋, ๋๋ค ๋ฐ๊พธ์ง ์๊ณ ๋ฌธ์์ด์ ํฉ์ณ๋ณด์.
๊ทธ๋ฌ๋ ค๋ฉด ๋จผ์ ๋ ๋ฌธ์์ด์ ๊ธธ์ด๋ฅผ ์ธก์ ํ ๋ค์ malloc์ ์ด์ฉํ๋ฉด ๋๋ค.
๊ทธ ๋ค์ ์ฒซ๋ฒ์งธ ๋ฌธ์์ด์ ์ ๊ณต๊ฐ์ ๋ณต์ฌํ๋ค์ strcat์ ํธ์ถํ์ฌ ๋๋ฒ์งธ ๋ฌธ์์ด์ ์ฐ๊ฒฐํ๋ค.
๐ malloc์ ์ด์ฉํ์ฌ ๋ฌธ์์ด ํฉ์น๊ธฐ
char* concat(const char* s1, const char* s2)
{
char* result;
result = malloc(strlen(s1) + strlen(s2) + 1);
if (result == NULL) {
printf("Error : malloc failed in concat\n");
exit(EXIT_FAILURE);
}
strcpy(result, s1);
strcat(result, s2);
return result;
}
์์ ๋ฌธ์์ด์ 2์ฐจ์ ๋ฐฐ์ด์ ์ ์ฅํ๋ฉด ๊ณต๊ฐ์ด ๋ญ๋น๋๋ค๋ ๋ฌธ์ ๋ก ์ธํด, ๋ฌธ์์ด์ ํฌ์ธํฐ๋ก ๊ฐ๋ฆฌํค๋ ๋ฐฐ์ด์ ์ด์ฉํ์๋ค. ์ด๋ ๋์ ํ ๋น๋ ๋ฌธ์์ด์๋ ์ด์ฉ๋ ์ ์๋ค.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_REMIND (50)
#define MSG_LEN (60)
int read_line(char str[], int n);
int main()
{
char* reminders[MAX_REMIND];
char day_str[3], msg_str[MSG_LEN + 1];
int day, i, j, num_remind = 0;
for (;;) {
if (num_remind == MAX_REMIND) {
printf("-- No space left --\n");
break;
}
printf("Enter day and reminder : ");
scanf("%2d", &day);
if (day == 0)
break;
sprintf(day_str, "%2d", day);
read_line(msg_str, MSG_LEN);
for (i = 0; i < num_remind; i++)
if (strcmp(day_str, reminders[i] < 0))
break;
for (j = num_remind; j > i; j--)
reminders[j] = reminders[j - 1];
reminders[i] = malloc(2 + strlen(msg_str) + 1);
if (reminders[i] == NULL) {
printf("-- No space left --\n");
break;
}
strcpy(reminders[i], day_str);
strcat(reminders[i], msg_str);
num_remind++;
}
printf("\nDay Reminder\n");
for (i = 0; i < num_remind; i++)
printf(" %s\n", reminders[i]);
return 0;
}
int read_line(char str[], int n)
{
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
str[i++] = ch;
str[i] = '\0';
return i;
}
C์์๋ ํ๋ก๊ทธ๋จ์ด ์คํ ์ค์ ๋ฐฐ์ด์ ๊ณต๊ฐ์ ํ ๋นํ ์ ์๋ค.
๋ฌธ์์ด์์์ ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ ์์์ ํฌ๊ธฐ๊ฐ ๋ฐ๋์ 1byte๊ฐ ์๋๋ผ๋ ์ ์ด๋ค. ๋ฐ๋ผ์ sizeof ์ฐ์ฐ์๋ฅผ ์ด์ฉํ์ฌ ํฌ๊ธฐ๋ฅผ ๊ณ์ฐํด์ฃผ์ด์ผ ํ๋ค.
n๊ฐ์ ์ ์๋ฅผ ๋ด๋ array๋ฅผ ๋ง๋ค์ด๋ณด์.
๋จผ์ ํฌ์ธํฐ ๋ณ์๋ฅผ ์ ์ธํด์ค๋ค.
int *a;
n์ด ์ด๋ฏธ ์ ์ธ๋์ด ์์ ๋, ์๋์ ๊ฐ์ด malloc์ ์ด์ฉํ์ฌ ๊ณต๊ฐ์ ํ ๋นํ ์ ์๋ค.
a = malloc(n * sizeof(int));
์ด๋ ๊ฒ ํ๊ณ ๋๋ฉด a๋ฅผ ๋ฐฐ์ด์ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
calloc์ <stdlib.h>์ ์ ์ธ๋์ด ์๋ค.
๐ calloc ํจ์
void *calloc(size_t nmemb, size_t size);
calloc์ size ํฌ๊ธฐ์ ๋ณ์๋ฅผ nmemb๊ฐ ๋งํผ ์ ์ฅํ ์ ์๋๋ก ํ๋ค.
๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ ๋ค์ calloc์ 0์ผ๋ก ์ด๊ธฐํํ๋ค.
๐ calloc ํจ์ ์ฌ์ฉ ์์
a = calloc(n, sizeof(int));
struct point { int x, y; } *p;
p = calloc(1, sizeof(struct point));
realloc์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ(ex.array)์ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๋ค.
๐ realloc ํจ์
void *realloc(void *ptr, size_t size);
ptr์ ๋ฐ๋์ malloc, calloc, realloc์ ์ํด ์ป์ด์ง ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก์ ๊ฐ๋ฆฌ์ผ์ผํ๋ค. size๋ ๋ธ๋ก์ ์๋ก์ด ์ฌ์ด์ฆ๋ฅผ ๋งํ๋ค. ๋ณดํต์ ์ฌํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ptr์ด ๋ค์ ๊ฐ๋ฆฌํจ๋ค.
๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก์ ํฌ๊ธฐ๋ฅผ ์ค์ด๋ผ๋ ์์ฒญ์ ๋ฐ์์ ๋ realloc์ ๋ธ๋ก์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ด๋์ํค์ง ์๊ณ ์ถ์ํด์ผ ํ๋ค. ํ์ฅํ ๋๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค. ๋ง์ฝ ๋ธ๋ก ๋ค์ ์ค๋ ๋ฐ์ดํธ๊ฐ ์ฌ์ฉ๋๊ณ ์์ด ํ์ฅํ ์ ์์ ๋, realloc์ ์ ๋ธ๋ก์ ๋ค๋ฅธ ๊ณณ์ ํ ๋นํ ๋ค์ ์ด์ ๋ธ๋ก์ ๋ด์ฉ์ ์ ๋ธ๋ก์ ๋ณต์ฌํ๋ค.
malloc๊ณผ ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ํจ์๋ ํ(heap)์ด๋ผ๊ณ ํ๋ ์ ์ฅ์ ํ(storage pool)์์ ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก์ ๊ฐ์ ธ์จ๋ค. ์ด๋ฌํ ํจ์๋ฅผ ๋๋ฌด ์์ฃผ ํธ์ถํ๊ฑฐ๋ ํฐ ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก์ ์์ฒญํ๋ฉด ํ์ด ์์ง๋์ด ํจ์๊ฐ ๋ ํฌ์ธํฐ๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
์ฌ์ง์ด ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ถ์ ํ์ง ๋ชปํด ๊ณต๊ฐ์ ๋ญ๋นํ ์ ์๋ค.
p = malloc(...);
q = malloc(...);
p = q;
์ ์์ ์ ๊ฒฝ์ฐ ์๋์ฒ๋ผ ๋๋ฏ๋ก ์ฒซ๋ฒ์งธ block์ ์์ํ ์ฐ์ด์ง ์๋๋ค.
์ด๋ ๊ฒ ๋ ์ด์ ์ฐ์ด์ง ์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ garbage๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ด๋ฐ garbage๊ฐ ๋ฐ์ํ๋ ํ๋ก๊ทธ๋จ์์๋ ๋ฉ๋ชจ๋ฆฌ ๋์(memory leak)์ด ๋ฐ์ํ๋ค. ๋ช๋ช ์ธ์ด์์๋ garbage collector์ ์ ๊ณตํ์ฌ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ฃผ๋ C๋ ๊ทธ๋ ์ง ์๋ค. ๋์ free ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋ถํ์ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํด ์ฃผ์ด์ผ ํ๋ค.
free ํจ์๋ <stdlib.h>์ ๋ค์ด ์๋ค.
๐ free ํจ์
void free(void *ptr);
๐ free ํจ์ ์ฌ์ฉ ์์
p = malloc(...);
q = malloc(...);
free(p);
p = q;
์ด๋ ๊ฒ ํ์ฌ p๊ฐ ๊ฐ๋ฆฌํค๋ ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ฝ์ ํด์ ํ ์ ์๋ค. ์ด ๋ free์ ์ธ์๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ํจ์์ ์ํด ๋ฐํ๋ ํฌ์ธํฐ์ด์ด์ผ ํ๋ค.
free(p)๋ p๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฒ์ ํด์ ํ์ง๋ง p ์์ฒด๋ฅผ ๋ฐ๊พธ์ง๋ ์๋๋ค.
๋ฐ๋ผ์ ์๋์ ๊ฐ์ด ์ฌ์ฉํ๊ฒ ๋๋ฉด ํผ๋์ ์ผ๊ธฐํ๋ค.
char *p = malloc(4);
...
free(p);
...
strcpy(p, "abc"); /*** WRONG ***/
์ฌ๋ฌ ํฌ์ธํฐ๋ค์ด ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋ธ๋ก์ ๊ฐ๋ฆฌํฌ ์ ์๊ธฐ ๋๋ฌธ์ ๋งค๋ฌ๋ฆฐ ํฌ์ธํฐ๋ค์ ์ฐพ๊ธฐ ์ด๋ ค์ธ ์ ์๋ค. ๋ธ๋ก์ด ํด์ ๋๋ฉด ๋ชจ๋ ํฌ์ธํฐ๊ฐ ๋งค๋ฌ๋ฆฐ ์ํ๋ก ์ ์ง๋๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ(linked list)๋ ๊ฐ ๋ ธ๋๊ฐ ๋ฐ์ดํฐ์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ํ ์ค๋ก ์ฐ๊ฒฐ๋์ด ์๋ ๊ฒ์ ๋งํ๋ค.
๋ง์ง๋ง ๋ ธ๋๋ null pointer๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ๋ฐฐ์ด์ ๋์์ด ๋ ์ ์๋ค. ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ด์ฉํ๋ฉด ์ฝ๊ฒ ์์๋ฅผ ์ถ๊ฐํ๊ณ ์ญ์ ํ ์ ์๋ค. ๊ทธ๋ฌ๋ "random access"๋ ๋ถ๊ฐ๋ฅํ๋ค. ์ด๋ ์ด์ ๊ฒฝ์ฐ ๋ชจ๋ ์์์ ์ ๊ทผํ๋๋ฐ ๋์ผํ ์๊ฐ์ด ์์๋์ง๋ง ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๊ฒฝ์ฐ ๊ฐ๊น์ธ์๋ก ๋น ๋ฅด๋ค.
๋ ธ๋๊ฐ ์ ์์ ๋ค์ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ง์ ๊ฐ์ง๊ณ ์๋ค๊ณ ๊ฐ์ ํ์.
struct node {
int value; /* data stored in the node */
struct node* next; /* pointer to the next node */
};
list๊ฐ ์ด๋์์๋ถํฐ ์์ํ๋์ง๋ฅผ ์ถ์ ํ๊ธฐ ์ํด ์ฒซ๋ฒ์งธ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ณ์๊ฐ ํ์ํ๋ค. ์ด๋ฅผ first๋ผ๊ณ ํ์๋ค.
struct node *first = NULL:
์ฒ์์ ๋น์ด ์์ผ๋ฏ๋ก first์ NULL๊ฐ์ ๋ถ์ฌํ์๋ค.
๋ ธ๋๋ฅผ ์๋ 3๋จ๊ณ๋ก ์์ฑํ๋ค.
1) ๋
ธ๋๋ฅผ ์ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ค.
2) ๋
ธ๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ค.
3) ๋ฆฌ์คํธ์ ๋
ธ๋๋ฅผ ๋ฃ๋๋ค.
๋ ธ๋๋ฅผ ์์ฑํ ๋ ๋ ธ๋๋ฅผ ๋ชฉ๋ก์ ์ฝ์ ํ ๋๊น์ง ๋ ธ๋๋ฅผ ์ผ์์ ์ผ๋ก ๊ฐ๋ฆฌํฌ ์ ์๋ ๋ณ์๊ฐ ํ์ํ๋ค. ์ด๋ฅผ new_node๋ผ๊ณ ํ์.
struct node *new_node;
malloc์ ์ฌ์ฉํ์ฌ ์ ๋ ธ๋์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ณ ๋ฐํ ๊ฐ์ new_node์ ์ ์ฅํ๋ค.
new_node = malloc(sizeof(struct node));
๋ค์์ผ๋ก, ๋ฐ์ดํฐ๋ฅผ ์ ๋ ธ๋์ value์ ์ ์ฅํ๋ค.
(*new_node).value = 10;
-> ์ฐ์ฐ์ : ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์กฐ์ฒด์ ๋ฉค๋ฒ์ ์ ๊ทผ
๐ -> ์ฐ์ฐ์ ์ฌ์ฉ ์์
new_node->value = 10;
-> ์ฐ์ฐ์๋ *๊ณผ .์ ๊ฒฐํฉ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค. new_node๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ ์ฐพ์๋ค์ ๊ทธ ๊ตฌ์กฐ์ฒด์ ๋ฉค๋ฒ๋ฅผ ์ ํํ๋ค.
-> ์ฐ์ฐ์๋ lvalue๋ฅผ ์์ฑํ๋ค.
๐ -> ์ฐ์ฐ์ ์ฌ์ฉ ์์ (2) - scnaf์์
scanf("%d", &new_node->value);
new_node : node๊ฐ ์ฝ์
๋๋ ์ง์ ์ ๊ฐ๋ฆฌํจ๋ค.
first : ์ฐ๊ฒฐ๋ฆฌ์คํธ์ ์ฒซ๋ฒ์งธ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
์ด ๋๊ฐ์ง๋ฅผ ์ด์ฉํ์ฌ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ฒซ๋ฒ์งธ์ ๋ ธ๋๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
๋จผ์ new_node์ next ๋ฉค๋ฒ๊ฐ ์ฒซ๋ฒ์งธ ๋ ธ๋์ ์ ์ฅ๋ ๊ฒ์ ๊ฐ๋ฆฌํค๊ฒ ํ๋ค.
new_node->next = first;
๋๋ฒ์งธ๋ก, first๊ฐ new_node๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๋ค.
first = new_node
๐ ๋น์ด์๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ 10 ์ถ๊ฐ ํ 20 ์ถ๊ฐ
์ด๋ฌํ ๊ณผ์ ์ add_to_list๋ผ๋ ์ด๋ฆ์ ํจ์๋ก ๋ง๋ค์ด๋ณด์. ํ๋ผ๋ฏธํฐ๋ list(์ถ๊ฐ ์ ๋ฆฌ์คํธ์ ์ฒซ๋ฒ์งธ ๋ ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ), n(์ฒซ๋ฒ์งธ ๋ ธ๋์ ์ ์ฅํ ์ ์) ๋๊ฐ์ง ์ด๋ค.
struct node* add_to_list(struct node* list, int n)
{
struct node* new_node;
new_node = malloc(sizeof(struct node));
if (new_node == NULL) {
printf("Error : malloc failed in add_to_list\n");
exit(EXIT_FAILURE);
}
new_node->value = n;
new_node->next = list;
return new_node;
}
first๊ฐ ๊ฐ๋ฆฌํค๋ ์ง์ ์ ๋ณํ์ง ์์์ผ๋ฏ๋ก add_to_list๋ฅผ ๋ค์ ํธ์ถํ๊ธฐ ์ ์ ๋ฐํ๊ฐ์ first์ ์ ์ฅํด์ฃผ์ด์ผ ํ๋ค.
first = add_to_list(first, 10);
first = add_to_list(first, 20);
๐ add_to_list ์ฌ์ฉ ์์ - ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์ ์ ๋ฃ๊ธฐ
struct node read_numbers(void)
{
struct node first = NULL;
int n;
printf("Enter a series of integers (0 to terminate) : ");
for (;;) {
scanf("%d", &n);
if (n == 0)
return first;
first = add_to_list(first, n);
}
}
๐ ํฌ์ธํฐ p๋ฅผ ์ด์ฉํ์ฌ ๋ ธ๋ ์ถ์
for (p = first; p != NULL; p = p->next) {
...
}
๐ search_list (1)
struct node* search_list(struct node* list, int n)
{
struct node* p;
for (p = list; p != NULL; p = p->next)
if (p->value == n)
return p;
return NULL
}
๐ search_list (2)
๋๋ฒ์งธ ๋ฐฉ๋ฒ์ p๋ฅผ ์ด์ฉํ์ง ์๊ณ list ์์ฒด๋ฅผ ์ด์ฉํ๋ ๊ฒ์ด๋ค.
struct node* search_list(struct node* list, int n)
{
for (; list != NULL; list = list->next)
if (list->value == n)
return list;
return NULL;
}
list๋ ๋ณต์ฌ๋ณธ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๊ฟ๋ ์๊ด์๋ค.
๐ search_list (3)
์ธ๋ฒ์งธ ๋ฐฉ๋ฒ์ while ๋ฌธ์ ์ด์ฉํ๋ ๊ฒ์ด๋ค.
struct node* search_list(struct node* list, int n)
{
while (list != NULL && list->value != n)
list = list->next;
return list;
}
์ฐ๊ฒฐ๋ฆฌ์คํธ์ ํฐ ์ฅ์ ์ ๋ ธ๋๋ฅผ ์ญ์ ํ๊ธฐ๊ฐ ์ฝ๋ค๋ ๊ฒ์ด๋ค. ๋ ธ๋๋ฅผ ์ญ์ ํ๋ ๊ฒ์ ๋ค์ 3๋จ๊ณ๋ก ์ด๋ฃจ์ด์ง๋ค.
1) ์ง์ธ ๋
ธ๋๊ฐ ์๋ ๊ณณ์ผ๋ก ๊ฐ๋ค.
2) ์ญ์ ๋ ๋
ธ๋๋ฅผ "ํต๊ณผ"ํ๋๋ก ์ด์ ๋
ธ๋๋ฅผ ๋ณ๊ฒฝํ๋ค.
3) free๋ฅผ ํธ์ถํ์ฌ ์ญ์ ๋ ๋
ธ๋๊ฐ ์ฌ์ฉํ๋ ๊ณต๊ฐ์ ์ง์ด๋ค.
1๋ฒ ๋จ๊ณ์์ ์ง์ธ ๋
ธ๋๊ฐ ์๋ ๊ณณ์ผ๋ก ๊ฐ๋ฉด 2๋ฒ ๋จ๊ณ์์ ์ด์ ๋จ๊ณ์ ๋ํ ์ผ์ ์ํํ ์๊ฐ ์๋ค.
์ด ๋ฌธ์ ๋ฅผ "trailing pointer" ๊ธฐ์ ์ ์ด์ฉํ์ฌ ํด๊ฒฐํ ์ ์๋ค.
1๋จ๊ณ์์ ๋ชฉ๋ก์ ๊ฒ์ํ ๋ ํ์ฌ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(cur) ๋ฟ๋ง ์๋๋ผ ์ด์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ(prev)๋ ์๊ฒ ํ๋ค.
for (cur = list, prev = NULL; cur != NULL && cur->value != n; prev = cur, cur = cur->next);
30 -> 40 -> 20 -> 10 ์ด ์ฐ๊ฒฐ๋์ด ์๋ ์ฐ๊ฒฐ๋ฆฌ์คํธ์์ 20์ ์ฐพ๋๋ค๊ณ ํ ๋ ์ ๊ตฌ๋ฌธ์ ์ด์ฉํ์ฌ 1๋จ๊ณ๋ฅผ ์ํํ๋ฉด ์๋์ ๊ฐ์ด ๋๋ค.
์ฌ๊ธฐ์ 2๋จ๊ณ๋ฅผ ์ํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๐ ์ญ์ ํ ๋ ธ๋์ ์ด์ ๋ ธ๋์ ๋ค์ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํด์ฃผ๊ธฐ
prev->next = cur-> next;
๐ 20 ์ญ์
free(cur);
์ด ์ธ๊ฐ์ง ๊ณผ์ ์ ํตํด ์ํ๋ ์ ์๋ฅผ ์ญ์ ํ๋๋ก ํ๋ ํจ์๋ฅผ ๋ง๋ค์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๐ delete_from_list
struct node* delete_from_list(struct node* list, int n)
{
struct node* cur, * prev;
for (cur = list, prev = NULL; cur != NULL && cur->value != n; prev = cur, cur = cur->next);
if (cur == NULL)
return list; /* n was not found */
if (prev == NULL)
list = list->next; /* n is in the first node */
else
prev->next = cur->next; /* n is in some other node */
free(cur);
return list;
}
์ ๋ ฌ๋ ๋ฆฌ์คํธ : ๋
ธ๋๋ค์ด ์์๋๋ก ์ ๋ ฌ๋์ด ์๋ ๊ฒฝ์ฐ
์ด ๊ฒฝ์ฐ ๋
ธ๋๋ฅผ ์ฝ์
ํ๋ ๊ฒ์ ๋ ์ด๋ ต์ง๋ง ๊ฒ์์ ๋ ๋น ๋ฅด๋ค.
๐ inventory2.c
/* Maintains a parts database (linked list version) */
#include <stdio.h>
#include <stdlib.h>
#include "readline.h"
#define NAME_LEN (25)
struct part {
int number;
char name[NAME_LEN + 1];
int on_hand;
struct part* next;
};
struct part* inventory = NULL; /* points to first part */
struct part* find_part(int number);
void insert(void);
void search(void);
void update(void);
void print(void);
int main(void)
{
char code;
for (;;) {
printf("Enter operation code : ");
scanf(" %c", &code);
while (getchar() != '\n');
switch (code) {
case 'i': insert();
break;
case 's': search();
break;
case 'u': update();
break;
case 'p': print();
break;
case 'q': return 0;
default: printf("Illegal code\n");
}
printf("\n");
}
}
struct part* find_part(int number)
{
struct part* p;
for (p = inventory; p != NULL && number > p->number; p = p->next);
if (p != NULL && number == p->number)
return p;
return NULL;
}
void insert(void)
{
struct part* cur, * prev, * new_node;
new_node = malloc(sizeof(struct part));
if (new_node == NULL) {
printf("Database is full; can't add more parts.\n");
return;
}
printf("Enter part number : ");
scanf("%d", &new_node->number);
for (cur = inventory, prev = NULL; cur != NULL && new_node->number > cur->number; prev = cur, cur = cur->next);
if (cur != NULL && new_node->number == cur->number) {
printf("Part already exists.\n");
free(new_node);
return;
}
printf("Enter part name : ");
read_line(new_node->name, NAME_LEN);
printf("Enter quantity on hand : ");
scanf("%d", &new_node->on_hand);
new_node->next = cur;
if (prev == NULL)
inventory = new_node;
else
prev->next = new_node;
}
void search(void)
{
int number;
struct part* p;
printf("Enter part number : ");
scanf("%d", &number);
p = find_part(number);
if (p != NULL) {
printf("Part name : %s\n", p->name);
printf("Quantity on hand : %d\n", p->on_hand);
}
else {
printf("Part not found.\n");
}
}
void update(void)
{
int number, change;
struct part* p;
printf("Enter part number : ");
scanf("%d", &number);
p = find_part(number);
if (p != NULL) {
printf("Enter change in quantity on hand : ");
scanf("%d", &change);
p->on_hand += change;
}
else
printf("Part not found.\n");
}
void print(void)
{
struct part* p;
printf("Part Number Part Name Quantity on Hand");
for (p = inventory; p != NULL; p = p->next)
printf("%7d %-25s11d\n", p->number, p->name, p->on_hand);
}
ํฌ์ธํฐ๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋ ํจ์๊ฐ ๋ค๋ฅธ ๊ณณ์ ๊ฐ๋ฆฌํค๊ฒ ํจ์ผ๋ก์จ ๋ณ์๋ฅผ ์์ ํ๊ณ ์ ํ ๋ ํฌ์ธํฐ์ ํฌ์ธํฐ๋ฅผ ์ด์ฉํ๋ค.
์์ ์์ฑํ add_to_list์์๋ new_node๋ฅผ ๋ฐํํ๋ค. ์ฌ๊ธฐ์ new_node๋ฅผ ๋ฐํํ๋ ๋์ ์ list๊ฐ new_node๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ๋ฐ๊พผ๋ค๊ณ ํด๋ณด์.
list = new_node
ํฌ์ธํฐ๋ pass by value๊ธฐ ๋๋ฌธ์ ์ ๊ตฌ๋ฌธ์ ์ ์๋ํ์ง ์๋๋ค.
์ฌ๋ฐ๋ฅธ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
๐ ํฌ์ธํฐ์ ํฌ์ธํฐ๋ฅผ ์ด์ฉํ add_to_list
void add_to_list(struct node** list, int n)
{
struct node* new_node;
new_node = malloc(sizeof(struct node));
if (new_node == NULL) {
printf("Error : malloc failed in add_to_list\n");
exit(EXIT_FAILURE);
}
new_node->value = n;
new_node->next = *list;
*list = new_node;
}
์ด๋ ๊ฒ ํ๋ฉด new_node์ next๊ฐ ์๋ list๊ฐ ๊ฐ๋ฆฌํค๋ ๊ณณ(์ฒซ๋ฒ์งธ์๋ ๋ ธ๋)๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋๊ณ , list๊ฐ ๊ฐ๋ฆฌํค๋ ๊ณณ์ new_node๋ก ๋ณํ๋ค.
ํจ์๋ค๋ ๋ฉ๋ชจ๋ฆฌ ์์น๋ฅผ ์ฐจ์งํ๊ธฐ ๋๋ฌธ์ C์์๋ ํฌ์ธํฐ๊ฐ ํจ์๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
์ a๋ถํฐ b๊น์ง ์ ๋ถํ๋ ํจ์๋ฅผ ๋ง๋ ๋ค๊ณ ํ ๋ f๋ฅผ ํจ์์ ๋ํ ํฌ์ธํฐ๋ก ์ ์ธํ ๊ฒ์ด๋ค.
double integrate(double (*f) (double), double a, double b);
f์์ ํฌ์ธํฐ๋ฅผ ๋ถ์ฌ์ f๊ฐ ํฌ์ธํฐ๋ฅผ ๋ฐํํ๋ ํจ์๊ฐ ์๋๋ผ ํจ์์ ๋ํ ํฌ์ธํฐ์์ ๋ํ๋ธ๋ค. * ์์ด ๊ทธ๋ฅ ํจ์์ฒ๋ผ ๋ณด์ด๊ฒ ์ฐ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
double integrate(double f(double), double a, double b);
integrate๋ฅผ ํธ์ถํ ๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ํจ์ ์ด๋ฆ์ ์ ๊ณตํ๋ค. ์๋ฅผ ๋ค์ด ์๋ ํจ์๋ sin ํจ์๋ฅผ 0๋ถํฐ ใ /2๊น์ง ์ ๋ถํ๋ค.
result = integrate(sin, 0.0, PI/2);
์ปดํ์ผ๋ฌ๋ ํจ์ ํธ์ถ์ ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋์ ํจ์์ ๋ํ ํฌ์ธํฐ๋ฅผ ์์ฑํ๋ค. ๋ฐ๋ผ์ ์ ์ฝ๋์์ sin์ ํธ์ถํ๋ ๊ฒ์ด ์๋๋ผ integrate์ sin์ ํฌ์ธํฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด ๋๋ค.
์ด ๊ฐ๋ ์ a๊ฐ ๋ฐฐ์ด์ ์ด๋ฆ์ธ ๊ฒฝ์ฐ a[i]๋ ๋ฐฐ์ด์ ํ ์์๋ฅผ ๋ํ๋ด๊ณ , a ์์ฒด๋ ๋ฐฐ์ด์ ๋ํ ํฌ์ธํฐ ์ญํ ์ ํ๋ ๊ฒ๊ณผ ์ ์ฌํ๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก f๊ฐ ํจ์๋ผ๋ฉด f(x)๋ ํจ์์ ํธ์ถ๋ก ์๊ฐํ์ง๋ง, f ๊ทธ์์ฒด๋ ํจ์์ ๋ํ ํฌ์ธํฐ๋ก ์ทจ๊ธํ๋ค.
integrate์์ ์๋์ ๊ฐ์ด f๊ฐ ๊ฐ๋ฆฌํค๋ ํจ์๋ฅผ ํธ์ถํ๋ค.
y = (*f)(x);
*f๊ฐ f๊ฐ ๊ฐ๋ฆฌํค๋ ํจ์๋ฅผ ๋ํ๋ด๊ธฐ ๋๋ฌธ์, integrate(sin, 0.0, PI/2) ๊ฐ ์คํ๋๋ ๋์ *f์ ํธ์ถ์ ์ฌ์ค์ sin์ ํ์ถ๊ณผ ๊ฐ๋ค.
C ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ฉํ ํจ์๋ค์ ๋๋ถ๋ถ์ด ํจ์ ํฌ์ธํฐ๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค. ๊ทธ ์ค ํ๋๊ฐ <stdlib.h>์ qsort ํจ์์ด๋ค.
qsort๋ ์ฐ๋ฆฌ๊ฐ ์ ํํ ๊ธฐ์ค์ ๋ฐ๋ผ ๋ชจ๋ ๋ฐฐ์ด์ ์ ๋ ฌํ ์ ์๋ ๊ธฐ๋ฅ์ด๋ค.
์ ๋ ฌ๋๋ ๋ฐฐ์ด์ ์์๋ค์ ์ด๋ค ํ์ ์ด๋ ๋ ์ ์๊ธฐ ๋๋ฌธ์, ๊ตฌ์กฐ์ฒด๋ ๊ณต์ ์ฒด ํ์ ์ qsort๋ ๋ ๋ฐฐ์ด ์์ ์ค ์ด๋ค ๊ฒ์ด "๋ ์์"์ง ๊ฒฐ์ ํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋ฅด์ณ์ผ ํ๋ค. ๋น๊ต ํจ์(comparison function)์ ์์ฑํ์ฌ qsort์๊ฒ ์ ๋ณด๋ฅผ ์ ๊ณตํ ๊ฒ์ด๋ค.
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
base : ์ด๋ ์ด์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
nmemb : ์ ๋ ฌ๋์ด์ผ ํ ์์์ ๊ฐฏ์
size : ๊ฐ ์์์ ์ฌ์ด์ฆ (๋ฐ์ดํธ ๋จ์)
compar : ๋น๊ตํ ํจ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ
๐ qsort ์ฌ์ฉ ์์
qsort(inventory, num_parts, sizeof(structpart), compare_parts);
๐ compare_parts ํจ์ ์์ฑํ๊ธฐ
qsort์์๋ ๋งค๊ฐ๋ณ์๋ก void ์ ํ์ ๋ฐ์ง๋ง, void ํฌ์ธํฐ๋ฅผ ํตํด part ๊ตฌ์กฐ์ฒด์ ๋ฉค๋ฒ์ ์ ๊ทผํ ์๊ฐ ์๋ค. ์ด ๋ฉค๋ฒ๋ค์ struct part* ์ ํ์ ํฌ์ธํฐ๊ฐ ํ์ํ๋ค.
์ด๋ฌํ ๋ฌธ์ ํด๊ฒฐ์ ์ํด compare_parts์ ๋งค๊ฐ๋ณ์ p, q๋ฅผ struct part*์ ๋ณ์์ ํ ๋นํ์ฌ ์ํ๋ ์ ํ์ผ๋ก ๋ณํํ์๋ค.
int compare_parts(const void* p, const void* q)
{
const struct part* p1 = p;
const struct part* q1 = q;
if (p1->number < q1->number)
return -1;
else if (p1->number == q1->number)
return 0;
else
return 1;
}
p์ q๋ const ํฌ์ธํฐ๊ธฐ ๋๋ฌธ์ const๋ก ์ ์ธ๋ ๋ณ์์๋ง ํ ๋น๋ ์ ์๋ค.
ํจ์ ํฌ์ธํฐ๋ฅผ ๋ณ์์ ์ ์ฅํ๊ฑฐ๋ ๋ฐฐ์ด์ ์์ ๋๋ ๊ตฌ์กฐ์ฒด๋ ๊ณต์ฉ์ฒด์ ๋ฉค๋ฒ๋ก์ ์ฌ์ฉํ ์ ์๋ค. ํจ์ ํฌ์ธํฐ๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์์ฑํ ์๋ ์๋ค.
๐ ํจ์์ ๋ํ ํฌ์ธํฐ๋ฅผ ์ ์ฅํ ์ ์๋ ๋ณ์
void (*pf)(int);
pf๋ intํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๊ณ , ๋ฐํ ๊ฐ์ด void ํ์ธ ๋ชจ๋ ํจ์๋ฅผ ๊ฐ๋ฆฌํฌ ์ ์๋ค.
pf๊ฐ ๊ฐ๋ฆฌํค๋ ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
(*pf)(i);
๋๋
pf(i);
๐ ์์๊ฐ ํจ์ ํฌ์ธํฐ์ธ ๋ฐฐ์ด
void (*file_cmd[])(void) = { new_cmd, open_cmd, close_cmd, close_all_cmd };
๋ฐฐ์ด ์ฒจ์๋ฅผ ์ด์ฉํ์ฌ ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค.
(*file_cmd[n]))(); /* or file_cmd[n](); */
๐ cos, sin ๋ฐ tan ํจ์์ ๊ฐ์ ๋ณด์ฌ์ฃผ๋ ํ๋ฅผ ์ถ๋ ฅ
/* Tabulates values of trigonometric functions */
#include <math.h>
#include <stdio.h>
void tabulate(double (*f)(double), double first, double last, double incr);
int main(void)
{
double final, increment, initial;
printf("Enter initial value : ");
scanf("%lf", &initial);
printf("Enter final value : ");
scanf("%lf", &final);
printf("Enter increment : ");
scanf("%lf", &increment);
printf("\n x cos(x)"
"\n ------- -------\n");
tabulate(cos, initial, final, increment);
printf("\n x sin(x)"
"\n ------- -------\n");
tabulate(sin, initial, final, increment);
printf("\n x tan(x)"
"\n ------- -------\n");
tabulate(tan, initial, final, increment);
return 0;
}
void tabulate(double (*f)(double), double first, double last, double incr)
{
double x;
int i, num_intervals;
num_intervals = ceil((last - first) / incr);
for (i = 0; i <= num_intervals; i++) {
x = first + i * incr;
printf("%10.5f %10.5f\n", x, (*f)(x));
}
}
๐ restrict
int* restrict p;
์์ฒ๋ผ restrict๋ก ์ ์ธ๋ ํฌ์ธํฐ๋ฅผ ์ ํ ํฌ์ธํฐ(restricted pointer)๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ด๋ ๊ฒ ์ ์ธํ๋ฉด p๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๊ฐ ๋ด๊ธด ๋ฉ๋ชจ๋ฆฌ์๋ ๋ค๋ฅธ ํฌ์ธํฐ๊ฐ ์ ๊ทผํ ์ ์๋ค.
๊ฐ์ฒด์ ์ ๊ทผํ๋ ๋ ๊ฐ์ง ์ด์์ ๋ฐฉ๋ฒ์ aliasing์ด๋ผ๊ณ ํ๋ค.
int* restrict p;
int* restrict q;
p = malloc(sizeof(int));
q = p;
*q = 0; /* casus undefined behavior */
p๊ฐ ์ ํ ํฌ์ธํฐ์ด๊ธฐ ๋๋ฌธ์, *q = 0 ์ด ์ ์๋์ง ์๋๋ค.
์ ํ๋ ํฌ์ธํฐ p๊ฐ ์ธ๋ถ ์ ์ฅ์ ํด๋์ค ์์ด ๋ก์ปฌ ๋ณ์๋ก ์ ์ธ๋๋ฉด, restrict๋ p๋ก ์ ์ธ๋ ๋ธ๋ก์ด ์คํ๋ ๋๋ง p์ ์ ์ฉ๋๋ค.
restrict ์ฌ์ฉ๋ฒ์ ๋ ์์๋ณด๊ธฐ ์ํด <string.h>์ ์๋ memcpy์ memmove๋ฅผ ์์๋ณด์.
๐ memcpy
void *memcpy(void* restrict s1, const void* restrict s2, size_t n);
memcpy๋ ํ ๊ฐ์ฒด์์ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋ฐ์ดํธ๋ฅผ ๋ณต์ฌํ๋ค.
๋ฐ๋๋ก memmove์์๋ restrict๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค.
๐ memmove
void *memmove(void *s1, const void *s2, size_t n);
์ฐจ์ด์ ์ ์์ค์ ํ๊น์ด ๊ฒน์น๋๋ผ๋ memmove๋ ์๋์ด ๋๋ค๋ ๊ฒ์ด๋ค.
์๋ฅผ ๋ค์ด, memmove๋ฅผ ์ด์ฉํ์ฌ ์ด๋ ์ด์ ์์๋ค์ ํ์นธ์ฉ ์ฎ๊ธธ ์ ์๋ค.
memmove(&a[0], &a[1], 99 * sizeof(int));
restrict๋ ์ปดํ์ผ๋ฌ์ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ฌ ๋ณด๋ค ํจ์จ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํจ์ผ๋ก์จ ์ต์ ํ(optimization)์ ํ๋ค.
๊ทธ๋ฌ๋ ๋ชจ๋ ์ปดํ์ผ๋ฌ๊ฐ ์ต์ ํ๋ฅผ ์๋ํ๋ ๊ฒ์ ์๋๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ํ์ ์ฌ์ฉํ์ง ์๋๋ค.
๋ฌธ์์ด ์ ์ฅ์ ์ข ๋ ์ ๋์ ์ด๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์์๋ณด์
struct vstring {
int len;
char chars[N];
};
์ด๋ฐ ๊ณ ์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฐ์ด์ ๋ฌธ์์ด์ ๊ธธ์ด๋ฅผ ์ ํํ๊ณ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ญ๋นํ๋ค.
C ํ๋ก๊ทธ๋๋จธ๋ค์ ์ ํต์ ์ผ๋ก ๋ฌธ์ ๊ธธ์ด๋ฅผ 1๋ก ์ ์ธํ๊ณ ๊ฐ ๋ฌธ์์ด์ ๋์ ์ผ๋ก ํ ๋นํจ์ผ๋ก์จ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์๋ค.
struct vstring {
int len;
char chars[1];
};
...
struct vstring* str = malloc(sizeof(struct vstring) + n - 1);
str->len = n;
์ด๋ฐ ๋ฐ๋ฒ์ "struct hack"์ด๋ ์ด๋ฆ์ผ๋ก ์๋ ค์ ธ ์๋ค.
struct hack์ ์ ์ฉ์ฑ ๋๋ฌธ์ C99์์๋ ์ ๋์ ๋ฐฐ์ด ๋ฉค๋ฒ(flexible array member) ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์๋ค.
๐ flexible array member
struct vstring {
int len;
char chars[]; /* flexible array member - C99 only */
};
...
struct vstring* str = malloc(sizeof(struct vstring) + n);
str->len = n;
์ ๋์ ๋ฐฐ์ด ๋ฉค๋ฒ๋ฅผ ๋ด๊ณ ์๋ ๊ตฌ์กฐ์ฒด๋ ์์ ํ์ง ์์ ์ ํ(incomplete type)์ด๋ค. ์ด๋ฌํ ํ์ ์ ๋ค๋ฅธ ๊ตฌ์กฐ์ฒด์ ๋ฉค๋ฒ๊ฐ ๋๊ฑฐ๋ ์ด๋ ์ด์ ์์๊ฐ ๋ ์ ์๋ค. ํ์ง๋ง ์ด๋ ์ด๊ฐ ์ด ๊ตฌ์กฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ฅผ ํฌํจํ ์๋ ์๋ค.