본문 바로가기

Programming/C

(26)
함수 포인터 1. 함수의 이름 배열의 이름은 배열의 시작주소를 의미한다. 마찬 가지로 함수의 이름은 함수가 저장된 (메모리의) 주소를 의미한다. 모든 함수는 프로그램 실행 시 메인 메모리(main memory)에 저장된 후 실행된다. 함수의 이름은 이 때의 주소값을 의미하는 것이다. 또한 배열의 이름이 상수이듯이 함수의 이름도 상수다. 2. 함수 포인터 변수의 선언 모든 포인터는 포인터 형이 결정되어야 적절한 선언이 가능하다. 다음과 같은 함수가 있다고 하자. int add(int a, int b); 이 함수의 반환형 선언은 int 고, 매개변수의 선언은 int a, int b 다. 그렇다면 이 함수의 포인터 형은 무엇일까? 함수의 포인터 형은 반환형과 매개변수의 선언 형태를 기준으로 정해진다. 위 함수의 포인터 선..
2차원 배열과 포인터 1. 2차원 배열 이름의 포인터 형 1차원 배열 이름은 상수 싱글 포인터다. 그럼 2차원 배열 이름은 더블 포인터일까? 다음과 같이 선언된 2차원 배열이 있다고 하자. int arr[3][3]; 당연히 아니다. 2차원 배열의 이름은 인덱스 기준으로 [0][0]의 주소, 즉 시작 주소다. 또한 arr[n] 은 arr 의 n 행의 시작 주소를 의미한다. 그렇다면 arr[0] 과 arr 은 같은 걸까? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include int main() { int arr[3][3]; printf("arr: %p\n", arr); printf("arr[0]: %p\n", arr[0]); printf("&arr[0][0]: %p\n\..
다차원 배열 1. 다차원 배열 1차원 배열은 논리적으로 1차원의 형태(선)를 취한다. 마찬가지로 2차원 배열은 2차원의 형태(면)를, 3차원 배열은 3차원의 형태(공간)를 취한다. 4차원 이상의 고차원 배열도 허용되지만, 이는 논리적으로 이해하는 것도 어렵고, 무엇보다도 불필요하다. 1차원 배열은 다음과 같이 선언한다. int arr1[10]; 다차원 배열은 다음과 같이 선언한다. int arr2[10][10]; int arr3[10][10][30]; 선언 방법은 1차원 배열과 유사하지만, 다차원 배열 특성상 가로 뿐 아니라 세로와 높이의 길이도 명시해야 한다. arr2 는 10×10 정사각형으로, arr3 은 10×10×30 사각기둥으로 비유할 수 있다. 2. 2차원 배열 2차원 배열의 형태는 다음과 같다. TYP..
다중 포인터 1. 포인터의 포인터 앞의 포인터 변수는 기본 타입(char, short, int, long, long, float, double) 변수를 가리키고 있다. 포인터의 포인터, 즉 이중 포인터(double pointer)는 기본 타입 변수가 아닌 포인터 변수를 가리키는 포인터 변수다. 이중 포인터 변수는 다음과 같이 선언한다. int** dptr; 언뜻 보면 어려워 보일 수 있지만, 사실 뭔가를 가리키고 있다는 것은 변함이 없다. 다만 가리키는 대상이 포인터 변수일 뿐이다. int형 변수와 포인터 변수는 저장하는 값의 유형이 다를 뿐이지, 결국 값을 저장할 수 있는 변수라는 점은 같았다. 마찬가지로 더블 포인터와 싱글 포인터는 저장하는 값이 포인터 변수의 주소인지, 기본 타입 변수의 주소인지 다를 뿐이다. ..
매개변수 1. CBV VS CBR 함수 호출 방식에는 CBV(Call-By-Value)와 CBR(Call-By-Reference)의 두 가지가 있다. 전자는 값에 의한 호출, 즉 값을 함수로 전달하는 방식이고 후자는 참조에 의한 호출, 즉 메모리 접근을 위한 주소값을 전달하는 방식이다. 따라서 앞에서 정의한 함수들은 모두 CBV 방식이라고 할 수 있다. 그런데 왜 이 둘을 구분하는 걸까? 다음과 같이 두 수의 값을 바꾸는 swap 함수를 정의한다고 해보자. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include void swap(int a, int b); int main() { int num1= 3, num2 = 5; printf("n..
포인터와 배열의 관계 1. 배열은 포인터다. 정확히 말하면, 배열의 이름은 그 값을 바꿀 수 없는 상수 포인터다. 앞에서 본 포인터 변수는 값을 바꿀 수 있었다. 1 2 3 4 5 6 7 8 9 10 11 12 #include int main() { int num1, num2; int* ptr = &num1; ptr = &num2; ... } cs 이렇게. 하지만 배열의 경우 값을 바꿀 수 없다. 1 2 3 4 5 6 7 8 9 10 11 #include int main() { int arr[3] = { 0, 1, 2 }; arr = &arr[2]; //에러 발생! ... } cs 배열은 시작 주소를 기준으로 해서 각 요소들의 주소를 지정한다. 배열 arr이 0x0030F780에 할당되었고, int 배열이라고 하자. 그럼 &..
포인터 1. 포인터 변수 포인터 변수(pointer variable)는 주소값을 저장하는 변수다. 메모리 공간은 1바이트 단위로 구분되어 있고, 단위에는 숫자가 매겨져 있다. 이 숫자를 주소, 번지 또는 어드레스(address)라 한다. 다음과 같이 변수가 선언되어 있다고 하자. 1 2 3 4 5 6 7 8 9 #include int main() { char ch = 'S'; int num1 = 6, num2 = 3; ... } cs 실제 메모리 공간에는 다음과 같이 저장된다. (다음과 같이 나란히 저장될 수도, 그렇지 않을 수도 있다.) 참고로 주소값을 2진수로 나타내려면 32자리를 나타내야 하기 때문에 보통 16진수로 나타낸다. S, 6, 3은 각각 0xffffdded, 0xffffddee, 0xffffdd..
1차원 배열 1. 배열 배열(array)은 여러 개의 변수들을 모아놓은 것이다. 단순히 여러 개의 변수를 선언한 것과는 차이가 있다. 예를 들어 다음과 같이 변수를 선언했다고 하자. 1 2 3 4 5 int num1; int num2; int num3; int num4; int num5; cs 이 때 메모리의 상태는 다음과 같다. 하지만 배열로 선언할 경우 다음과 같다. 배열은 말 그대로 변수들을 나열한 것, 즉 변수들의 배열이다. 그냥 변수를 여러 개 선언한 것과는 메모리에 할당되는 형태가 다르다. 따라서 선언하는 방법도, 접근하는 방법도 다르다. 배열은 다음과 같이 선언한다. int arr[5]; 이 선언문은 다음과 같이 구성된다. int: 배열을 이루는 요소(변수)들의 자료형 arr: 배열의 이름 [5]: 배열..