Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

구조체 멤버의 크기와 오프셋을 출력하는 C 프로그램 작성 방법


문제 정의

구조체(structure)를 정의하고, 멤버 변수들의 크기(size)와 오프셋(offset)을 화면에 출력하는 C 프로그램을 작성해 보겠습니다.

구조체란 서로 다른 자료형의 변수들을 하나의 이름 아래 묶어 놓은 집합체로, 관련된 데이터를 하나의 단위로 관리할 수 있게 해주는 사용자 정의 자료형입니다.

구조체 선언의 일반 형식

datatype member1;
struct tagname{
   datatype member2;
   datatype member n;
};

여기서 struct는 구조체를 정의할 때 사용하는 키워드이며, tagname은 구조체의 이름을 지정합니다. member1, member2 등은 구조체를 구성하는 개별 데이터 항목(멤버)을 의미합니다.

예시

struct book{
   int pages;
   char author[30];
   float price;
};

위 예시는 책의 페이지 수, 저자, 가격 정보를 담는 book이라는 이름의 구조체를 정의한 것입니다.

구조체 변수 선언 방법

구조체 변수를 선언하는 방법에는 세 가지가 있습니다.

방법 1 — 구조체 정의와 동시에 변수 선언

struct book{
   int pages;
   char author[30];
   float price;
}b;

방법 2 — 태그명 없이 변수 선언

struct{
   int pages;
   char author[30];
   float price;
}b;

이 방법은 구조체 이름 없이 바로 변수를 선언하는 것으로, 나중에 동일한 형태의 구조체 변수를 추가로 선언할 수 없다는 단점이 있습니다.

방법 3 — 구조체 정의 후 별도로 변수 선언

struct book{
   int pages;
   char author[30];
   float price;
};
struct book b;

가장 일반적으로 사용되는 방식으로, 필요할 때마다 같은 구조체형 변수를 여러 개 선언할 수 있습니다.

구조체의 초기화와 멤버 접근

멤버와 구조체 변수 사이의 연결은 멤버 연산자(도트 연산자, .)를 사용하여 설정합니다. 구조체는 다음과 같은 방법으로 초기화할 수 있습니다.

방법 1 — 선언과 동시에 초기화

struct book{
   int pages;
   char author[30];
   float price;
} b = {100, "balu", 325.75};

방법 2 — 구조체 정의 후 초기화

struct book{
   int pages;
   char author[30];
   float price;
};
struct book b = {100, "balu", 325.75};

방법 3 — 멤버 연산자를 이용한 초기화

struct book{
   int pages;
   char author[30];
   float price;
};
struct book b;
b.pages = 100;
strcpy(b.author, "balu");
b.price = 325.75;

방법 4 — scanf 함수를 이용한 입력

struct book{
   int pages;
   char author[30];
   float price;
};
struct book b;
   scanf("%d", &b.pages);
   scanf("%s", b.author);
   scanf("%f", &b.price);

이제 데이터 멤버를 포함하는 구조체를 선언하고, 각 멤버의 오프셋 값과 구조체 전체 크기를 출력해 보겠습니다. 멤버의 오프셋이란 구조체의 시작 위치부터 해당 멤버까지 떨어진 바이트 거리를 의미하며, stddef.h 헤더 파일에 정의된 offsetof 매크로를 사용하면 손쉽게 확인할 수 있습니다.

프로그램 코드

#include<stdio.h>
#include<stddef.h>
struct tutorial{
   int a;
   int b;
   char c[4];
   float d;
   double e;
};
int main(){
   struct tutorial t1;
   printf("the size 'a' is :%d\n",sizeof(t1.a));
   printf("the size 'b' is :%d\n",sizeof(t1.b));
   printf("the size 'c' is :%d\n",sizeof(t1.c));
   printf("the size 'd' is :%d\n",sizeof(t1.d));
   printf("the size 'e' is :%d\n",sizeof(t1.e));
   printf("the offset 'a' is :%d\n",offsetof(struct tutorial,a));
   printf("the offset 'b' is :%d\n",offsetof(struct tutorial,b));
   printf("the offset 'c' is :%d\n",offsetof(struct tutorial,c));
   printf("the offset 'd' is :%d\n",offsetof(struct tutorial,d));
   printf("the offset 'e' is :%d\n\n",offsetof(struct tutorial,e));
   printf("size of the structure tutorial is :%d",sizeof(t1));
   return 0;
}

실행 결과

the size 'a' is :4
the size 'b' is :4
the size 'c' is :4
the size 'd' is :4
the size 'e' is :8
the offset 'a' is :0
the offset 'b' is :4
the offset 'c' is :8
the offset 'd' is :12
the offset 'e' is :16

size of the structure tutorial is :24

결과 분석

각 멤버의 크기를 살펴보면 int는 4바이트, char 배열은 4바이트, float는 4바이트, double은 8바이트입니다. 오프셋을 보면 첫 번째 멤버 a는 구조체의 시작 위치인 0부터 배치되고, 이후 멤버들은 앞선 멤버들의 크기만큼 순차적으로 떨어진 위치에 배치됩니다. 따라서 구조체 전체 크기는 4+4+4+4+8 = 24바이트가 됩니다.

참고로 실제 환경에서는 컴파일러가 CPU의 메모리 정렬(alignment) 요건을 충족시키기 위해 멤버 사이에 패딩(padding)을 삽입하는 경우가 있으므로, 구조체의 실제 크기는 멤버 크기의 단순 합보다 커질 수 있습니다. sizeof와 offsetof를 활용하면 이러한 메모리 배치 상황을 정확하게 파악할 수 있습니다.