C언어 포인터의 고급 활용과 사용자 정의 데이터 타입 정리

1. 다중 포인터 (Multi-level Pointers)

포인터 변수의 주소를 저장하는 포인터를 다중 포인터라고 합니다. 주소를 타고 여러 번 접근하는 구조를 가집니다.


int data = 100;
int *p1 = &data;      // 1단계 포인터
int **p2 = &p1;      // 2단계 포인터 (이중 포인터)
int ***p3 = &p2;     // 3단계 포인터 (삼중 포인터)
    

2. 안전한 포인터 사용: NULL 포인터와 와일드 포인터

2.1 NULL 포인터

포인터가 아무것도 가리키지 않음을 명시할 때 사용합니다. 초기화되지 않은 포인터로 인한 사고를 방지하고, 함수의 에러 발생 시 반환값으로 활용됩니다.

  • 용도: 변수 선언 시 초기화, 할당 실패 시 반환 처리.
  • 주의: NULL 포인터는 실제 메모리 주소가 없으므로 역참조(dereferencing) 시 런타임 에러가 발생합니다.

float *f_ptr = NULL;
if (f_ptr != NULL) {
    // 안전한 접근
}
    

2.2 와일드 포인터 (Wild Pointer)

적절한 주소로 초기화되지 않았거나, 이미 해제된 메모리를 가리키고 있는 포인터를 의미합니다. 이는 시스템 불안정의 주범이 됩니다.

  • 선언 후 초기화하지 않은 경우.
  • 배열 범위를 벗어난 접근.
  • 지역 변수의 주소를 반환하거나 이미 해제(free)된 메모리를 가리키는 경우.

3. 열거형 (Enum)

연관된 정수형 상수들을 이름으로 정의하여 코드의 가독성을 높이는 사용자 정의 타입입니다.


enum ProcessStatus {
    READY,      // 0
    EXECUTING,  // 1
    SUSPENDED,  // 2
    TERMINATED = 10  // 직접 지정 가능
};

enum ProcessStatus current = READY;
    

기본적으로 0부터 1씩 증가하며 할당되지만, 특정 값을 직접 지정할 수도 있습니다. 내부적으로는 정수(int)로 처리됩니다.

4. 구조체 (Struct)

서로 다른 타입의 데이터를 하나의 단위로 묶어서 관리할 때 사용합니다.


struct Employee {
    int id;
    char name[64];
    double salary;
};

// 변수 선언 및 초기화
struct Employee emp1 = {101, "John Doe", 5500.0};
    

4.1 구조체 멤버 접근 및 포인터

일반 변수는 . 연산자를 사용하고, 포인터 변수는 -> 연산자를 사용하여 멤버에 접근합니다.


struct Employee *ptr = &emp1;

// 동일한 접근 방식
ptr->id = 202;
(*ptr).id = 202;
emp1.id = 202;
    

4.2 메모리 정렬 (Memory Alignment)

컴퓨터는 성능 최적화를 위해 데이터를 특정 바이트 단위(패딩)로 정렬하여 저장합니다. 따라서 구조체의 실제 크기는 멤버들의 크기 합계보다 클 수 있습니다.

  • 멤버 정렬: 각 멤버는 자신의 크기 또는 시스템 기준의 배수 위치에 배치됩니다.
  • 전체 정렬: 구조체 전체 크기는 가장 큰 멤버 크기의 배수가 되도록 조정됩니다.
  • 제어: #pragma pack(n)을 사용하여 정렬 기준을 변경할 수 있습니다.

printf("구조체 크기: %zu\n", sizeof(struct Employee));
    

태그: c-language pointer struct Enum memory-management

6월 22일 02:47에 게시됨