프로그래밍 기법
핵심 요약
- 배열 (Arrays): 동일한 자료형의 데이터 집합을 메모리의 연속된 공간에 저장하는 자료구조이다. 인덱스를 통해 각 요소에 빠르게 접근할 수 있으며, 1차원뿐만 아니라 다차원 형태로도 구성이 가능하다.
- 포인터 (Pointers): 변수의 메모리 주소값을 직접 저장하고 다루는 변수이다. 메모리에 대한 직접적인 접근을 가능하게 하여 동적 메모리 할당, 배열 및 구조체의 효율적 관리 등 고급 프로그래밍 기법의 근간을 이룬다.
- 구조체 (Structs): 서로 다른 자료형의 변수들을 하나의 논리적 단위로 묶어 새로운 자료형을 정의하는 기능이다. 배열과 달리 이질적인 데이터 그룹을 만들 수 있어, '레코드'와 같은 복잡한 데이터 형태를 표현하는 데 매우 유용하다.
- 재귀호출 (Recursive Calls): 함수가 자기 자신을 다시 호출하는 프로그래밍 기법이다. 복잡한 문제를 동일한 구조를 가진 더 작은 문제들로 분할하여 해결하는 데 효과적이며, 특정 알고리즘을 간결하게 표현할 수 있게 한다.
배열 (Arrays): 심층 분석
배열은 동일한 자료형의 원소(element)들을 모아 메모리에 연속적으로 할당한 자료 그룹이다.
각 원소는 고유한 번호인 '인덱스(index)'를 통해 구별되며, C 언어에서 인덱스는 항상 0부터 시작한다.
1차원 배열
가장 기본적인 형태의 배열로, 데이터를 한 줄로 나열한 구조를 가진다.
- 선언 형식: 자료형 배열이름 [배열 요소의 개수];
- 자료형: 배열에 저장될 모든 원소의 데이터 타입을 지정한다.
- 배열이름: 변수 이름 규칙에 따라 정의한다.
- 배열 요소의 개수: 대괄호([]) 안에 배열의 크기를 명시한다.
- 메모리 할당: 배열 선언 시 할당되는 총 메모리 크기는 (자료형의 메모리 크기) × (배열 요소의 개수)로 결정된다.
| 배열 선언 예 | 의미 | 메모리 할당 크기 |
|---|---|---|
| char c[100]; | char형 원소 100개로 구성된 배열 c (c[0]~c[99]) | 1바이트 × 100 |
| int i[100]; | int형 원소 100개로 구성된 배열 i (i[0]~i[99]) | 4바이트 × 100 |
| short s[100]; | short형 원소 100개로 구성된 배열 s (s[0]~s[99]) | 2바이트 × 100 |
| long l[100]; | long형 원소 100개로 구성된 배열 l (l[0]~l[99]) | 4바이트 × 100 |
- 초기화: 선언과 동시에 중괄호
{ }안에 초깃값 리스트를 지정하여 초기화할 수 있다.- 자료형
배열이름[배열크기] = { 초깃값 리스트 }; - 초깃값의 개수가 배열 크기보다 작으면 나머지 원소들은 0으로 자동 초기화된다.
- 초깃값의 개수가 배열 크기보다 많으면 컴파일 오류가 발생한다.
- 자료형
- 문자 배열: 문자열(String)을 저장하기 위해 char형 배열을 사용한다. 문자열은 문자들의 연속적인 나열이며, 큰따옴표(" ")로 표현된다.
- 초기화 방법: 문자열 리터럴
"String"을 사용하거나, 개별 문자를 리스트{'S', 't', 'r', 'i', 'n', 'g', '\0'}로 지정할 수 있다.
- 초기화 방법: 문자열 리터럴
다차원 배열
2차원 이상의 배열로, 행과 열 또는 면, 행, 열의 구조를 논리적으로 표현한다.
- 선언 형식:
- 2차원: 자료형
배열이름 [행 개수][열 개수]; - 3차원: 자료형
배열이름 [면 개수][행 개수][열 개수];
- 2차원: 자료형
- 구조:
- 논리적 구조: 2차원은 표(table), 3차원은 입방체(cube) 형태로 인식된다.
- 물리적 구조: 메모리에는 차원과 관계없이 모든 원소가 1차원적으로 연속되게 저장된다.
- 초기화: 1차원 배열과 유사하게 초깃값 리스트를 사용한다. 차원별로 중첩된 중괄호를 사용하여 구조를 명확히 하거나, 모든 값을 나열하여 순서대로 초기화할 수 있다.
포인터 (Pointers): 심층 분석
포인터는 변수의 메모리 주소값을 값으로 가지는 특별한 변수이다.
포인터 변수가 특정 변수의 주소를 저장하는 것을 '해당 변수를 가리킨다(pointing)'고 표현하며,
이를 통해 메모리 영역에 직접 접근하고 제어할 수 있다.
선언 및 개념
- 정의: "변수의 메모리 주소값" 그 자체 또는 주소값을 저장하는 "포인터 변수"를 의미한다.
- 선언 형식: 자료형
*포인터이름;*기호는 해당 변수가 포인터임을 나타낸다.- 자료형은 포인터 자체가 아닌, 포인터가 가리킬
주요 연산자
포인터는 두 가지 핵심 연산자를 통해 동작한다.
| 연산자 | 이름 | 설명 | 사용 예시 |
|---|---|---|---|
& | 주소 연산자 | 변수 앞에 사용하여 해당 변수의 시작 메모리 주소를 반환한다. | ptr = &i; |
* | 참조 연산자 | 포인터 변수 앞에 사용하여, 해당 포인터가 가리키는 메모리 주소에 저장된 값을 읽거나 쓴다. | *ptr = 20; 또는j = *ptr; |
포인터 초기화 방법
포인터 변수에 유효한 주소값을 할당하는 주요 방법은 다음과 같다.
- 주소 연산자
&사용: 기존 변수의 주소를 할당한다. - 동적 메모리 할당:
malloc등의 함수를 통해 할당된 메모리의 시작 주소를 지정한다. - 문자열 리터럴 할당:
char*포인터에 문자열의 시작 주소를 직접 지정한다. - 배열 이름 사용: 배열의 이름은 그 자체로 배열의 시작 주소를 의미하므로 포인터에 할당할 수 있다.
- 배열 첫 번째 요소의 주소 사용:
&array[0]와 같이 배열의 첫 번째 요소의 주소를 명시적으로 지정한다.
고급 활용
- 포인터 배열 (Pointer Array): 포인터 변수들로 구성된 배열.
자료형 *포인터배열이름[배열크기];형태로 선언한다. 각 배열의 원소가 포인터이므로, 여러 개의 문자열이나 동적으로 할당된 메모리 블록들을 효율적으로 관리할 수 있다. - 포인터의 포인터 (Pointer to Pointer): 다른 포인터 변수의 주소를 저장하는 포인터로, 이중 포인터라고도 한다.
자료형 **포인터이름;형태로 선언한다. 포인터 배열을 함수 인자로 전달하거나, 함수 내에서 포인터 변수 자체의 값을 변경할 때 사용된다.
구조체 (Structs): 심층 분석
구조체는 하나 이상의 변수를 묶어 새로운 자료형으로 정의하는 기능이다. 배열과 달리, 서로 다른 자료형의 변수들을 멤버(항목)로 포함할 수 있다.
핵심 개념
- 정의: "서로 다른 자료형을 그룹으로 묶을 수 있"는 사용자 정의 자료형.
- 배열과의 차이점: 배열은 동일 자료형(homogeneous)의 집합인 반면, 구조체는 다른 자료형(heterogeneous)의 집합을 만들 수 있다.
- 활용: 이름, 입사 연도, 연봉 등 여러 필드(field)로 구성된 레코드(record)와 같은 복잡한 데이터를 표현하는 데 매우 유용하다.
선언 및 사용
구조체는 3단계의 과정을 거쳐 사용된다.
- 구조체형 선언: struct 키워드를 사용하여 구조체의 이름과 내부 멤버 변수들을 정의한다.
- 구조체 변수 선언: 정의된 구조체형을 사용하여 변수를 선언한다.
- 구조체 변수 사용: 선언된 변수의 내부 멤버에 접근하여 데이터를 저장하거나 사용한다.
- 선언 형식:
- 사용 형식: struct 구조체형이름 구조체변수이름;
데이터 항목 참조
구조체 변수의 멤버에 접근하기 위해 두 가지 연산자가 사용된다.
| 연산자 | 이름 | 설명 | 사용 예시 |
|---|---|---|---|
| . | 점 연산자 | 구조체 변수의 데이터 항목을 지정할 때 사용한다. (예: Lee[i].name) | |
| -> | 화살표 연산자 | 구조체를 가리키는 포인터를 통해 데이터 항목을 지정할 때 사용한다. (예: ptr->name) |
참고: 화살표 연산자
p->member는(*p).member와 완전히 동일한 표현이다.