핵심 정리

자료형 변환

언어에서는 종류가 다른 자료형끼리 저장을 하면 컴파일 경고가 발생합니다. 이때 명시적 형 변환을 사용하면 컴파일 경고가 발생하지 않으며 코드의 의도를 명확하게 나타낼 수 있습니다.

// 명시적 형 변환
(자료형)변수
(자료형)

다른 자료형으로 된 포인터로 변환하려면 자료형 뒤에 *를 붙여서 변환하면 됩니다. 포인터를 변환한 뒤 역참조하려면 맨 앞에 역참조 연산자 *를 붙여주면 됩니다.

// 특정 자료형 포인터로 변환
(자료형 *)포인터

// 특정 자료형 포인터로 변환한 뒤 역참조
*(자료형 *)포인터

void 포인터는 자료형이 정해져 있지 않으므로 역참조를 할 수 없습니다. 따라서 다른 포인터 자료형을 변환한 뒤 역참조하면 됩니다.

// void 포인터를 다른 자료형으로 변환한 뒤 역참조
*(자료형 *)void포인터

구조체 포인터를 변환한 뒤 멤버에 접근하려면 자료형 변환 부분과 포인터를 모두 ( ) (괄호)로 묶어주고 -> (화살표 연산자)를 사용합니다.

// 특정 구조체 포인터로 변환
(struct 구조체이름 *)포인터
(구조체별칭 *)포인터
(구조체별칭포인터)포인터

// 특정 구조체 포인터로 변환한 뒤 멤버에 접근
((struct 구조체이름 *)포인터)->멤버
((구조체별칭 *)포인터)->멤버
((구조체별칭포인터)포인터)->멤버

포인터 연산

포인터 변수에는 메모리 주소가 들어있으므로 포인터 변수를 +, - 연산하면 메모리 주소가 바뀝니다. 따라서 메모리에서 순방향, 역방향으로 이동할 수 있습니다. 메모리 주소가 증가, 감소하는 단위는 포인터를 선언한 자료형의 크기이므로 증가, 감소 크기는 "sizeof(자료형) * 더하거나 빼는 값"이 됩니다.

// 포인터 연산
포인터 + 
포인터 - 
포인터++
포인터--
++포인터
--포인터

즉, 포인터를 증가시키면 메모리에서 순방향으로 이동하고(포인터 전진, forward), 감소시키면 역방향으로 이동합니다(포인터 후진, backward).

포인터 연산과 동시에 역참조를 하려면 포인터 연산을 한 부분을 ( ) (괄호)로 묶어준 뒤 맨 앞에 역참조 연산자 *를 붙여주면 됩니다.

*(포인터 + )
*(포인터 - )

void 포인터는 자료형의 크기가 정해져 있지 않기 때문에 +, - 연산을 해도 얼마만큼 이동할지 알 수가 없습니다. 따라서 void포인터는 다른 포인터로 변환한 뒤 포인터 연산을 합니다.

// void 포인터를 다른 자료형으로 변환한 뒤 포인터 연산
(자료형 *)void포인터 + 
(자료형 *)void포인터 - 
++(자료형 *)void포인터
--(자료형 *)void포인터
((자료형 *)void포인터)++
((자료형 *)void포인터)--

// void 포인터를 다른 자료형으로 변환하여 포인터 연산을 한 뒤 역참조
*((자료형 *)void포인터 + )
*((자료형 *)void포인터 - )
*(++(자료형 *)void포인터)
*(--(자료형 *)void포인터)
*(((자료형 *)void포인터)++)
*(((자료형 *)void포인터)--)

구조체 포인터를 포인터 연산한 뒤 멤버에 접근하려면 포인터 연산을 한 부분을 ( ) (괄호)로 묶어준 뒤 -> (화살표 연산자)를 사용합니다.

// 구조체 포인터를 포인터 연산한 뒤 멤버에 접근
(포인터 + )->멤버
(포인터 - )->멤버

// 포인터를 구조체 포인터로 변환하여 포인터 연산한 뒤 멤버에 접근
((struct 구조체이름 *)포인터 + )->멤버
((struct 구조체이름 *)포인터 - )->멤버

malloc 함수로 동적 메모리를 할당했을 때는 ++, --로 포인터 연산에 주의해야 합니다. 만약 ++, -- 포인터 연산으로 메모리 주소가 바뀐 상태에서 free 함수로 메모리 해제를 하면 에러가 발생합니다. free 함수에는 반드시 처음에 메모리를 할당할 때 받은 주소(포인터)를 넣어주어야 합니다.