그러한 배열을 선언할 때는 그 크기를 지정해 주어야 하며
다만 배열을 선언하면서 동시에 그 값을 채워줄 때는 크기를 지정하지 않아도 되는 것으로 알고 있었다.
그래서 char a[] = "ab"; 는 가능해도 char a[]; 는 에러가 된다.
그런데 구조체 속에 선언한 크기 미지정의 배열은 어떻게 될까? 에러일까?
정답부터 말하면 가능하다.
좀더 말해서 해당 구조체 메모리 할당시 구조체 안에 크기 미지정의 배열에 대한
메모리는 할당되지 않는 것 같다.
이는 구조체에서 이 크기 미지정의 배열 대신 포인터를 넣으면
포인터 크기, 주로 4byte가 잡히는 것과 비교할 때 특이한 점이라 할 수 있다.
이러한 특징을 이용해서 구조체의 가장 끝 필드(Field)값으로 이러한 크기 미지정 배열을 넣고,
이 구조체에 대한 메모리를 할당할 때 구조체 자체의 메모리 크기에 더해서
해당 배열의 타입(type)의 배수 크기로 추가적인 메모리를 잡으면
그 배열 이름과 인덱스(index)로 추가된 메모리를 접근할 수 있다.
이 경우 구조체 메모리를 할당할 때마다 해당 배열의 크기를 원하는 만큼으로 조절할 수 있는 장점이 있다.
아래 코드는 이를 확인하기 위해 작성한 것으로서
특이한 사항은 추가적인 메모리를 할당하던 안 하던 크기 미지정 배열의 주소가
int 변수의 주소값에서 4만큼 큰 주소값이라는 것이다.
메모리는 할당되지 않지만 주소값은 있는 것처럼 보이는 것이다.
#include <stdio.h>
#include <stdlib.h>
typedef struct _T1{
int a; // 4bytes
char * ch; // 4byte
}T1, *PT1;
typedef struct _T2{
int a; // 4bytes
char ch[]; // 0byte
}T2, *PT2;
int main()
{
PT1 p1 = (PT1)malloc(sizeof(PT1)+sizeof(char)*5);
PT2 p2 = (PT2)malloc(sizeof(PT2)+sizeof(char)*5);
PT2 p3 = (PT2)malloc(sizeof(PT2));
printf("T1 size : [%d], T2 size : [%d]\n", sizeof(T1), sizeof(T2));
printf("sizeof(int) : [%d]\n\n", sizeof(int));
// error - a->ch[0] = 'A';
p2->ch[0] = 'B';
printf("p1 : [%x], &p1->a : [%x], &p1->ch : [%x]\n\n", p1, &p1->a, &p1->ch);
printf("p2->ch[0] : [%c]\n", p2->ch[0]);
printf("p2 : [%x], &p2->a : [%x]\n", p2, &p2->a);
printf("&p2->ch : [%x], &p2->ch : [%x], &p2->ch[0] : [%x]\n", &p2->ch, p2->ch, &p2->ch[0]);
printf("\np3 : [%x], &p3->a : [%x]\n", p3, &p3->a);
printf("&p3->ch : [%x], &p3->ch : [%x], &p3->ch[0] : [%x]\n", &p3->ch, p3->ch, &p3->ch[0]);
return 0;
}
'Lang, Tool, Env' 카테고리의 다른 글
static 통한 접근 제한 (0) | 2007.05.16 |
---|---|
CONTAINING _RECORD macro (0) | 2007.04.26 |
Verify() (0) | 2007.04.14 |
다시 체계적으로 배우는 C언어 포인터 개인 정리[비공개] (0) | 2007.03.13 |
다시 체계적으로 배우는 C 언어 포인터 (0) | 2007.03.11 |