본문 바로가기

자린고비 독학하기/자린고비 코딩하기

C 언어 코딩 도장 빨리 끝내기 - 4: 구조체 / 공용체 / 구조체 비트 필드

반응형

 

c 언어 기초 그만 좀 보고 싶어서 빨리 끝내 보려고 합니다 

4 : 구조체 / 공용체 / 구조체 비트 필드

 

 

오.. 머리 뽀개지는데... 

 

 

핵심 정리 1: https://dojang.io/mod/page/view.php?id=799

 

C 언어 코딩 도장: 핵심 정리

typedef로 자료형의 별칭 정의하기 typedef를 사용하면 구조체를 포함하여 모든 자료형의 별칭을 정의할 수 있습니다. typedef 자료형 별칭; // 자료형의 별칭 정의 typedef 자료형* 별칭; // 자료형 포인터의 별칭 정의 구조체 구조체는 struct 키워드로 정의하며 관련 정보를 하나의 의미로 묶을 때 사용합니다. // 구조체 정의하기 struct 구조체이름 { 자료형 멤버이름; }; // 구조체 변수 선언하기 struct 구조체이름

dojang.io

 

핵심 정리

typedef로 자료형의 별칭 정의하기

typedef를 사용하면 구조체를 포함하여 모든 자료형의 별칭을 정의할 수 있습니다.

typedef 자료형 별칭; // 자료형의 별칭 정의

typedef 자료형* 별칭; // 자료형 포인터의 별칭 정의

 

구조체

구조체는 struct 키워드로 정의하며 관련 정보를 하나의 의미로 묶을 때 사용합니다.

// 구조체 정의하기

struct 구조체이름 { 자료형 멤버이름; };

// 구조체 변수 선언하기

struct 구조체이름 변수이름;

// 구조체 변수를 선언하는 동시에 값을 초기화

struct 구조체이름 변수이름 = { .멤버이름1 = 값1, .멤버이름2 = 값2 };

struct 구조체이름 변수이름 = { 값1, 값2 };



// 구조체를 정의하는 동시에 변수 선언하기

struct 구조체이름 { 자료형 멤버이름; } 변수;

// 구조체를 정의하면서 구조체 별칭 정의하기

typedef struct 구조체이름 { 자료형 멤버이름; } 구조체별칭;

// 익명 구조체 정의하기

typedef struct { 자료형 멤버이름; } 구조체별칭;

// 구조체 별칭으로 변수 선언하기

구조체별칭 변수이름;

 

구조체 멤버에 접근할 때는 . (점)을 사용합니다.

 

struct 구조체이름 변수이름; 변수.멤버; // 구조체 멤버의 값을 가져옴

변수.멤버 = 값;  // 구조체 멤버에 값을 저장

 

 

malloc 함수로 구조체 포인터에 메모리를 할당할 수 있으며 이때는 멤버에 접근할 때 -> (화살표 연산자)를 사용합니다.


// 구조체 포인터에 동적 메모리 할당

struct 구조체이름 *포인터이름 = malloc(sizeof(struct 구조체이름));

// 구조체 별칭으로 포인터를 선언하고 동적 메모리 할당

구조체별칭 *포인터이름 = malloc(sizeof(구조체별칭));



포인터->멤버; // 구조체 포인터 멤버의 값을 가져옴

포인터->멤버 = 값; // 구조체 포인터 멤버에 값을 저장



free(포인터); // 구조체 메모리 해제

 

구조체 포인터에는 & (주소 연산자)로 구조체 변수의 메모리 주소를 구해서 할당할 수 있습니다.

구조체포인터 = &구조체변수;

 

 

핵심 정리 2: https://dojang.io/mod/page/view.php?id=774

 

C 언어 코딩 도장: 핵심 정리

구조체 멤버 정렬 C 언어는 CPU에서 메모리에 접근하는 효율을 높이기 위해 구조체를 일정한 크기로 정렬을 합니다. 이때 멤버 중에서 큰 자료형 크기의 배수로 정렬하며 남는 공간을 채우는 것을 패딩이라 부릅니다. // 1 + 4 = 5 바이트 크기의 구조체 struct PacketHeader { char flags; // 1바이트 int offset; // 4바이트 }; printf("%d\n", sizeof(struct PacketHeader)); //

dojang.io

핵심 정리

구조체 멤버 정렬

C 언어는 CPU에서 메모리에 접근하는 효율을 높이기 위해 구조체를 일정한 크기로 정렬을 합니다. 이때 멤버 중에서 큰 자료형 크기의 배수로 정렬하며 남는 공간을 채우는 것을 패딩이라 부릅니다.

// 1 + 4 = 5 바이트 크기의 구조체 struct PacketHeader { char flags; // 1바이트 int offset; // 4바이트 }; printf("%d\n", sizeof(struct PacketHeader)); // 8: 가장 큰 자료형은 int. int의 크기 4바이트로 정렬 // 남는 3바이트는 패딩

구조체의 정렬 크기를 조절하려면 컴파일러에서 제공하는 지시자를 사용해야 합니다.

Visual Studio, GCC 4.0 이상

#pragma pack(push, 정렬크기) #pragma pack(pop)

GCC 4.0 미만

__attribute__((aligned(정렬크기),packed))

구조체의 내용을 0으로 설정하기

구조체의 내용을 모두 0으로 설정하려면 memset 함수를 사용합니다.

memset(구조체포인터, 0, sizeof(struct 구조체));

구조체의 내용을 복사하기

구조체의 내용을 복사하려면 memcpy 함수를 사용합니다.

memcpy(목적지포인터, 원본포인터, sizeof(struct 구조체));

구조체 배열

구조체 변수를 선언하려면 [ ] (대괄호)에 크기를 지정합니다. 구조체 배열의 멤버에 접근하려면 [ ]에 인덱스를 지정한 뒤 .으로 접근합니다.

// 구조체 배열 선언하기 struct 구조체이름 변수이름[크기]; // 구조체 배열을 선언하는 동시에 값을 초기화 struct 구조체이름 변수이름[크기] = { { .멤버이름1 = 1, .멤버이름2 = 2 }, { .멤버이름1 = 3, .멤버이름2 = 4 } }; struct 구조체이름 변수이름[크기] = { { 1, 2 }, { 3, 4 } }; 배열[인덱스].멤버; // 구조체 배열에서 요소의 멤버 값을 가져옴 배열[인덱스].멤버 = ; // 구조체 배열에서 요소의 멤버에 값을 저장

구조체 포인터 배열

구조체 포인터 배열을 선언하려면 포인터 변수 이름 뒤에 [ ]를 붙인 뒤 크기를 지정합니다. 이때 배열의 요소에는 메모리를 할당해야 하며 멤버에 접근할 때는 [ ]에 인덱스를 지정한 뒤 ->로 접근합니다.

// 구조체 포인터 배열 선언하기 struct 구조체이름 *포인터이름[크기]; // 구조체 포인터 배열에 메모리 할당하기 for (int i = 0; i < 크기; i++) // 배열 크기만큼 반복 { 배열[i] = malloc(sizeof(struct 구조체)); // 각 요소에 구조체 크기만큼 메모리 할당 } 배열[인덱스]->멤버; // 구조체 포인터 배열에서 요소의 멤버 값을 가져옴 배열[인덱스]->멤버 = ; // 구조체 포인터 배열에서 요소의 멤버에 값을 저장 // 구조체 포인터 배열의 메모리 해제하기 for (int i = 0; i < 크기; i++) // 배열 크기만큼 반복 { free(포인터[i]); // 각 요소의 동적 메모리 해제 }

 

핵심 정리 3: https://dojang.io/mod/page/view.php?id=775

 

C 언어 코딩 도장: 핵심 정리

공용체 공용체는 union 키워드로 정의하며 멤버 중에서 가장 큰 자료형의 공간을 공유합니다. // 공용체 정의하기 union 공용체이름 { 자료형 멤버이름; }; // 공용체 변수 선언하기 union 공용체이름 변수이름; // 공용체를 정의하는 동시에 변수 선언하기 union 공용체이름 { 자료형 멤버이름; } 변수; // 공용체를 정의하면서 공용체 별칭 정의하기 typedef union 공용체이름 { 자료형 멤버이름; } 공용체별칭; // 익명 공용체

dojang.io

 

 

핵심 정리

공용체

공용체는 union 키워드로 정의하며 멤버 중에서 가장 큰 자료형의 공간을 공유합니다.

// 공용체 정의하기 union 공용체이름 { 자료형 멤버이름; }; // 공용체 변수 선언하기 union 공용체이름 변수이름; // 공용체를 정의하는 동시에 변수 선언하기 union 공용체이름 { 자료형 멤버이름; } 변수; // 공용체를 정의하면서 공용체 별칭 정의하기 typedef union 공용체이름 { 자료형 멤버이름; } 공용체별칭; // 익명 공용체 정의하기 typedef union { 자료형 멤버이름; } 공용체별칭; // 공용체 별칭으로 변수 선언하기 공용체별칭 변수이름;

다음 공용체는 가장 큰 자료형인 int의 공간을 공유하며 공용체의 크기는 int의 크기와 같습니다.

union A { int x; // 가장 큰 자료형인 int의 공간을 공유함 char y; short z; };

공용체 멤버에 접근할 때는 .(점)을 사용합니다.

union 공용체이름 변수이름; 변수.멤버; // 공용체 멤버의 값을 가져옴 변수.멤버 = ; // 공용체 멤버에 값을 저장

malloc 함수로 공용체 포인터에 메모리를 할당할 수 있으며 이때는 멤버에 접근할 때 -> (화살표 연산자)를 사용합니다.

// 공용체 포인터에 동적 메모리 할당 union 공용체이름 *포인터이름 = malloc(sizeof(union 공용체이름)); // 공용체 별칭으로 포인터를 선언하고 동적 메모리 할당 공용체별칭 *포인터이름 = malloc(sizeof(공용체별칭)); 포인터->멤버; // 공용체 포인터 멤버의 값을 가져옴 포인터->멤버 = ; // 공용체 포인터 멤버에 값을 저장 free(포인터); // 공용체 메모리 해제

공용체도 포인터에 공용체 변수의 메모리 주소를 구해서 할당할 수 있습니다. 또한, 공용체도 배열 및 배열 포인터로 만들 수 있고, memset, memcpy 함수를 사용할 수 있으며 방식은 구조체와 같습니다.

구조체와 공용체 함께 사용하기

구조체 안에 구조체를 멤버로 넣을 수 있으며 구조체와 공용체는 섞어서 쓸 수 있습니다.

struct 구조체A { 자료형 멤버이름; }; struct 구조체B { 자료형 멤버이름 struct 구조체A 멤버이름; // 구조체A를 멤버로 가짐 }; struct 구조체B 변수이름; 변수.멤버.멤버 // 구조체 안의 구조체 멤버 값을 가져옴 변수.멤버.멤버 = ; // 구조체 안의 구조체 멤버에 값을 저장

구조체 포인터의 멤버는 -> 연산자로 접근하고, 변수는 .을 사용하여 순차적으로 접근합니다.

struct 구조체B *포인터이름 = malloc(sizeof(struct 구조체B)); 포인터->멤버.멤버; // 구조체 포인터의 구조체에서 멤버 값을 가져옴 포인터->멤버.멤버 = ; // 구조체 포인터의 구조체에서 멤버에 값을 저장 free(포인터); // 구조체 메모리 해제

구조체는 공용체를 멤버로 가질 수 있습니다.

union 공용체C { 자료형 멤버이름; }; // 구조체와 공용체를 섞어서 사용 struct 구조체C { 자료형 멤버이름; union 공용체C 멤버이름; // 공용체A를 멤버로 가짐 }; 변수.멤버.멤버; // 구조체 안의 공용체 멤버 값을 가져옴 변수.멤버.멤버 = ; // 구조체 안의 공용체 멤버에 값을 저장

구조체 안에 다른 구조체의 포인터를 멤버로 가지고 있다면 바깥 구조체 포인터에 메모리를 먼저 할당한 뒤 멤버에 메모리를 할당합니다. 메모리를 해제할 때는 반대로 멤버를 먼저 해제한 뒤 바깥 구조체를 해제합니다.

struct 구조체A { 자료형 멤버이름; }; struct 구조체B { 자료형 멤버이름; struct 구조체A *멤버이름; // 구조체A의 포인터를 멤버로 가짐 }; struct 구조체B *포인터이름 = malloc(sizeof(struct 구조체B)); // 바깥 구조체의 포인터에 메모리 할당 포인터->구조체A포인터 = malloc(sizeof(struct 구조체A)); // 멤버 포인터에 메모리 할당 변수->멤버->멤버; // 구조체 포인터의 구조체 포인터에서 멤버 값을 가져옴 변수->멤버->멤버 = ; // 구조체 포인터의 구조체 포인터에서 멤버에 값을 저장 free(포인터->구조체A포인터); // 구조체 멤버의 메모리를 먼저 해제 free(포인터); // 구조체 메모리 해제

익명 구조체와 익명 공용체를 함께 사용하면 같은 값이지만 이름과 형태를 달리하여 접근할 수 있습니다.

struct 구조체이름 { union { // 익명 공용체 struct { // 익명 구조체 자료형 멤버이름A; // 변수로 접근할 때 사용 자료형 멤버이름B; 자료형 멤버이름C; }; 자료형 배열이름[3]; // 배열로 접근할 때 사용 }; }; struct 구조체이름 변수이름; 변수.멤버A; // 같은 값을 변수로 접근 변수.배열[0]; // 같은 값을 배열의 인덱스로 접근

 

 

핵심 정리 4: https://dojang.io/mod/page/view.php?id=776

 

C 언어 코딩 도장: 핵심 정리

구조체 비트 필드 구조체의 멤버를 선언할 때 : (콜론) 뒤에 비트 수를 지정하면 멤버를 비트 단위로 저장할 수 있습니다. 비트 필드의 자료형은 정수 자료형만 사용할 수 있습니다. struct 구조체이름 { 정수자료형 멤버이름 : 비트수; }; 비트 필드와 공용체를 함께 사용하기 비트 필드와 공용체를 함께 사용하면 비트 필드값을 한꺼번에 접근할 수도 있고 각각의 비트 필드값을 따로 접근할 수도 있습니다. struct Flags { union { // 익명

dojang.io

 

핵심 정리

구조체 비트 필드

구조체의 멤버를 선언할 때 : (콜론) 뒤에 비트 수를 지정하면 멤버를 비트 단위로 저장할 수 있습니다. 비트 필드의 자료형은 정수 자료형만 사용할 수 있습니다.

struct 구조체이름 { 정수자료형 멤버이름 : 비트수; };

비트 필드와 공용체를 함께 사용하기

비트 필드와 공용체를 함께 사용하면 비트 필드값을 한꺼번에 접근할 수도 있고 각각의 비트 필드값을 따로 접근할 수도 있습니다.

struct Flags { union { // 익명 공용체 struct { // 익명 구조체 unsigned short a : 3; // a는 3비트 크기 unsigned short b : 2; // b는 2비트 크기 unsigned short c : 7; // c는 7비트 크기 unsigned short d : 4; // d는 4비트 크기 }; // 합계 16비트 unsigned short e; // 2바이트(16비트) }; };

열거형

열거형은 정수형 상수에 이름을 붙입니다. 열거형에 초깃값을 지정하지 않으면 0부터 시작합니다.

// 열거형 정의하기 enum 열거형이름 { 1 = 초깃값, 2, 3, }; // 값의 개수까지 포함된 열거형 정의하기 enum 열거형이름 { 1 = 초깃값, 2, 3, 열거형Count // 값의 개수를 나타내는 항목 }; // 열거형 변수 선언하기 enum 열거형이름 변수이름; 변수 = 열거형값1; // 열거형 변수에 열거형 값 할당 // 열거형을 정의하면서 열거형 별칭 정의하기 typedef enum 열거형이름 { 1 = 초깃값, 2, 3 } 열거형별칭; // 열거형을 정의하면서 열거형 별칭 정의하기(값의 개수 포함) typedef enum 열거형이름 { 1 = 초깃값, 2, 3 열거형Count // 값의 개수를 나타내는 항목 } 열거형별칭; // 열거형 별칭으로 변수 선언하기 열거형별칭 변수이름; // 열거형을 switch에 활용하기 switch (열거형변수) { case 열거형값1: 코드1; break; case 열거형값2: 코드2; break; } // 열거형을 for에 활용하기 for (열거형이름 i = 열거형값1; i < 열거형Count; i++) // 초깃값은 열거형값1, { // 열거형Count보다 작을 때까지 반복 코드; }

반응형