2 분 소요

이 포스팅은 서울시립대학교 인공지능학과 백형부 교수님의 ‘컴퓨터시스템’ 강좌의 중간고사 이전 범위 수업 내용에 대한 정리를 담고 있습니다.

수업 자료 출처: Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, 3rd Edition

포인터

C언어에서 포인터는 기본적으로 메모리 주소를 저장하는 변수입니다. 이는 C언어의 핵심적인 특성 중 하나로, 프로그램의 메모리 공간에 직접 접근하고 조작할 수 있는 능력을 제공합니다. 포인터를 이해하고 활용하는 것은 이 수업에서 중요한 부분이며, 특히 메모리 주소를 할당하고 관리하는 과정을 자주 다루기 때문에 C언어에서 포인터의 개념을 명확히 파악하는 것이 필수적입니다.

변수

image-20240414004319618

image-20240414004344077

C 코드에서 변수의 메모리 주소를 확인하는 방법 중 하나는 앰퍼센드(&) 기호를 사용하는 것입니다. 이 기호를 변수 이름 앞에 붙이면, 해당 변수가 메모리 상에서 할당된 위치, 즉 주소를 얻을 수 있습니다. 이를 통해 변수가 실제로 컴퓨터의 메모리 어느 부분에 저장되어 있는지 확인할 수 있습니다.

예시 01

image-20240414004918947

위의 예시는 C 언어에서 변수의 메모리 주소를 다루는 방법을 보여줍니다. 우선, number라는 이름의 변수에 10이라는 값이 저장되었습니다. 그 다음으로, 포인터형 변수 p가 선언되어 number 변수의 주소를 저장하게 됩니다. 이 포인터 변수 p는 주소를 저장하는 역할을 합니다.

포인터형 변수 앞에 별표(*)를 붙이는 문법은 해당 포인터가 가리키는 주소에 저장된 값을 참조할 때 사용됩니다. 따라서, *pp가 가리키는 주소, 즉 number 변수에 저장된 10이라는 값을 의미합니다. 결과적으로, 이 코드를 실행하면 10이 출력되는 것을 확인할 수 있습니다.

아래 예시들은 자세한 설명 없이, 변수, 메모리에 대한 도식을 주로 나타냅니다.

예시 02

image-20240414010101957

image-20240414013817701

예시 03

image-20240414013855135

image-20240414014209141

예시 04

image-20240414014239202

image-20240414015155469

왼쪽 예시에서는 함수가 실행될 때 새로운 지역변수가 선언되고 그 변수에 값이 할당되는 것에 불과합니다. 그래서 함수 실행 후에도 원래의 값에는 변화가 없습니다.

예시 05

image-20240414015243701

예시 04에서 볼 수 있듯이, 함수 내부에서 변수를 단순히 선언하는 것만으로는 우리가 원하는 값의 교환이 이루어지지 않습니다. 우리가 원하는 값의 교환을 위해서는 포인터형 변수를 선언하여 해당 주소의 값을 직접 접근하여 변경해야 합니다.

예시 06

image-20240414015623341

image-20240414015938757

기본적으로 배열의 이름은 해당 배열의 가장 첫 번째 원소의 주소를 가리킵니다.

예시 07

image-20240414020035688

image-20240414020544994

포인터형 변수는 단순히 하나의 메모리 주소만을 저장하는 것이 아니라, 연속된 메모리 영역에 대한 접근 방법을 제공합니다. 예를 들어, 포인터형 변수 p가 배열의 첫 번째 요소를 가리키고 있다면, p[0]은 배열의 첫 번째 요소를, p[1]은 두 번째 요소를, 그리고 이런 식으로 p[n]은 배열의 (n+1)번째 요소를 참조하게 됩니다. 이는 포인터가 배열과 유사하게 동작할 수 있음을 의미합니다.

예시 08

image-20240414021153274

image-20240414021508347

예시 09

image-20240414021532344

image-20240414022212101

배열의 이름으로 선언된 변수(a)는 덧셈 연산이 불가능합니다. 단, 동일한 주소를 가리키는 포인터형 변수(*p)는 덧셈 연산이 가능합니다.

예시 10

image-20240414022247726

image-20240414024412614

*p++*(p++)으로 동작합니다.

(*p)++에서 런타임 오류가 발생하는 주된 이유는, 포인터 p가 초기화되지 않아 유효하지 않은 메모리 위치를 참조하고 있기 때문입니다. 즉, p가 가리키는 위치가 정의되지 않았거나, 프로그램이 접근 권한을 가지지 않은 메모리 영역을 가리킬 때, 해당 위치에 대한 연산을 시도하면 시스템 수준에서 오류가 발생합니다. 이러한 상황은 포인터를 사용할 때 주의해야 하는 중요한 사항 중 하나입니다.

명령어 자체는 문법적으로 올바르지만, p가 가리키는 메모리 주소가 유효한 값으로 초기화되지 않았을 경우, 즉 쓰레기 값이나 무효한 메모리 주소에 접근하려고 하면 런타임 오류가 발생합니다. 이는 시스템이 프로그램의 잘못된 메모리 접근을 방지하기 위해 내부적으로 설정된 보호 메커니즘에 의한 것입니다.

댓글남기기