C 언어에서 배열은 동일한 유형의 요소 집합을 저장하는 기본 구조입니다. 인덱스를 통한 빠른 접근을 제공하며 포인터와 밀접하게 연관되어 있습니다. 배열은 정적으로, 자동으로(스택에), 또는 동적으로(힙에) 선언할 수 있습니다. 할당 유형은 배열의 생활 주기, 코드의 다양한 부분에서의 접근 가능성 및 메모리 관리 요구 사항에 영향을 미칩니다.
질문 배경
초기 C는 정적 및 자동 배열만 정의할 수 있었지만 동적 메모리 할당(malloc, calloc, free 함수)의 출현으로 인해 새로운 설계 패턴이 생겨 코드의 유연성이 향상되었습니다.
문제
개발자는 배열의 크기, 생활 주기 및 정리를 잘못 설정하는 경우가 많아 메모리 누수, 경쟁 조건 및 메모리 손상으로 이어집니다.
해결책
작업에 따라 저장 유형을 신중하게 선택하고, 초기화를 주의 깊게 추적하며, 동적 배열에 대해 적시에 메모리를 해제하는 것입니다.
코드 예시:
#include <stdio.h> #include <stdlib.h> int main() { // 자동 (스택에) int auto_arr[5] = {1,2,3,4,5}; // 정적 (프로그램이 작동하는 동안 존재) static int static_arr[5]; // 동적 (힙에) int *dyn_arr = malloc(5 * sizeof(int)); for (int i = 0; i < 5; i++) dyn_arr[i] = i * 2; // 사용 for (int i = 0; i < 5; i++) printf("%d ", dyn_arr[i]); printf(" "); free(dyn_arr); return 0; }
주요 특징:
동적 배열의 크기를 sizeof를 통해 알 수 있나요?
아니요, sizeof(ptr)는 동적 배열의 크기가 아닌 포인터의 크기를 반환합니다. 크기를 수동으로 저장하거나 별도의 변수를 사용하는 것이 필요합니다.
int* arr = malloc(10 * sizeof(int)); printf("%zu ", sizeof(arr)); // 포인터의 크기, 배열이 아님
배열의 경계를 넘어가면 어떻게 되나요?
C 언어에는 배열 경계에 대한 자동 검사가 없습니다: 범위를 넘어서는 접근은 정의되지 않은 동작을 초래합니다. 오류는 실행 단계에서만 발견되거나 전혀 발견되지 않을 수 있습니다.
함수에서 지역(자동) 배열을 반환할 수 있나요?
아니요! 함수 내부에서 선언된 배열은 함수가 종료된 후에 삭제됩니다. 그런 배열을 반환하면 이미 해제된 메모리에 접근하게 됩니다.
int* create_wrong_array() { int arr[10]; return arr; // 오류: 스택에 대한 포인터 반환 }
개발자가 스택에 배열을 만들고 이를 함수에서 포인터로 반환합니다. 프로그램이 가끔 충돌하거나 잡음을 반환합니다.
장점:
단점:
크기와 함께 포인터를 전달하여 동적 할당을 사용하는 것, 메모리를 free를 통해 정리합니다. 모든 메모리 해제 사례가 단위 테스트로 확인됩니다.
장점:
단점: