본문 바로가기

Programming/C

가변길이 구조체(flexible array member)

반응형

커널 코드를 살펴보다, 아래 예제와 같이

struct 선언 마지막에 size가 0인 array를 선언하는 코드를 발견하였다.

1
2
3
4
5
6
7
struct account {
    int age;
    int gender;
    int name_length;
    char name[];
}
 
cs

정확한 이름은 C99에서는 flexible array member 라고 한다. 

(이전에는 struct hack, zero length array라고도 했다는데 아직까지도 다양하게 불리는 것 같다.)


[목적]

배열의 크기를 고정시키지 않고 동적으로(dynamic) 선택하고 싶을 때 사용한다. 

name의 경우, 대략 문자10개로 #define MAX_NAME_LEN 10 으로 하고 char name[MAX_NAME_LEN]

으로 할 수 있으나, 

name의 사이즈가 문자 1개 일 경우, 나머지가 낭비되며 

또한 사용자는 name의 사이즈가 문자 10개를 보다 큰 사이즈로 설 싶은데 시스템적으로 크기를 제한을 두는게

과연 서비스제공자(프로그래머)로서 맞는 것인가?


[사용법]

선언 시 structure의 마지막 멤버로 size가 0인 array를 선언한다 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//올바른 사용
struct account {
    int age;
    int gender;
    int name_length;
    char name[];  /* 0-sized-array가 가장 마지막에 위치하여야 한다. */
}
 
//잘못된 사용1
struct account {
    char name[];  /* 0-sized-array가 중간에 있으면 안 된다 */
    int age;
    int gender;
    int name_length;
}
//잘못된 사용3
struct account {
    int age;
    int gender;
    char name[];  /* 0-sized-array가 중간에 있으면 안 된다 */
    int name_length;
}
 
//잘못된 사용2
struct account {
    int age;
    char name[];  /* 0-sized-array가 중간에 있으면 안 된다 */
    int gender;    
    int name_length;
}
cs


sizeof(struct account) 를 해 보면, size는 12(byte)가 출력이 된다. 

name[]은 size를 차지하지 않는다


1
2
3
4
    ...
    person = malloc(sizeof(struct account) + (sizeof(char* actual_size + 1));
    person->name_length = actual_size;
    ...
cs


[malloc과 차이?]

오늘 살펴 본 가변길이 구조체를  사용한다면

아래 그림과 같이 메모리 상에 연속적으로 공간이 할당 된다. 




아래와 같이 선언하고, name만 malloc했을 때는?

1
2
3
4
5
6
7
struct account {
    int age;
    int gender;
}
 
char *name;
cs

struct account 변수와 name은 물리적으로 연속하지 않은 공간에 할당될 것이다.

(속도적인 측면에서도 주로 같이 참조되는 데이터들 끼리는 메모리 공간상에서 연속적인 것이 좋음)

또한 name도 논리적으로 account 정보에 속함에도 불구하고 struct에서 나옴으로써 

관련 데이터를 묶어서 관리하는 struct의 목적에도 위배된다. 




참고)

1. struct의 멤버로 flexible array member를 얘기하였으나, union과 class에도 사용이 가능 

2. C99이전에는 char name[] 대신 char name[0] 으로 size를 명시해주었다고 한다. 

(둘은 완전 같음. 그러나 []은 C99표준, [0]은 비표준)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//표준
struct account {
    int age;
    int gender;
    int name_length;
    char name[];
}
 
//표준X
struct account {
    int age;
    int gender;
    int name_length;
    char name[0]; 
}
cs




(참고 사이트: https://www.forbes.com/sites/quora/2013/05/14/what-is-the-advantage-of-using-zero-length-arrays-in-c/#aaf601b213a0

                     https://docs.oracle.com/cd/E19205-01/819-5265/bjazj/index.html)



반응형