Chapter3. 포인터와 배열 함께 이해하기!!!
- 포인터와 배열의 관계
- 배열의 이름은 무엇을 의미하는가?
- 배열의 이름 = 포인터, 값을 바꿀 수 없는 '상수 형태의 포인터' 이다
- 배열의 이름은 배열의 시작 주소 값을 의미하며, 그 형태는 값의 저장이 불가능한 상수 이다
- 따라서 *연산도 가능하다
- 1차원 배열이름의 포인터 형과 배열이름을 대상으로 하는 *연산!
- 1차원 배열이름의 포인터 형은 배열 이름이 가리키는 대상을 기준으로 결정된다
- ex) int arr[5]; // arr은 int형 포인터 상수, double arr[7]; // arr은 double형 포인터 상수
- ex) int arr[3] = { 1, 2, 3}; *arr += 100; // arr 에는 {101, 2, 3} 의 형태로 저장되어 있다
- 포인터를 배열의 이름처럼 사용할 수도 있다
- ex)int arr[3] = {1, 2, 3};, int* ptr = &arr[0];(int* ptr = arr;), ptr[1 ] += 100 // arr = {1, 102, 3}의 형태로 저장됨
- 많이 사용되지 않는다, 하지만 사용할 수는 있다.
- 배열의 이름은 무엇을 의미하는가?
- 포인터 연산
- 포인터 변수를 대상으로 하는 증가 및 감소연산
- TYPE 형 포인터를 대상으로 n 증가 = n*sizeof(TYPE) 의 크기만큼 증가
- 중요한 결론!! arr[i] == *(arr+i)
- *(arr+1) 과 arr[i] 은 같은 의미 이다
- *arr+1 은 arr[0]의 값+1을 의미하므로 *arr+i != *(arr+1)
- 포인터 변수를 대상으로 하는 증가 및 감소연산
- 상수 형태의 문자열을 가리키는 포인터
- 두 가지 형태의 문자열 표현
- char str1[ ] = "My String"; // 길이 자동 계산, M의 주소 값이 str1에 저장됨
- char * str2 = "Your String"; // Your String 의 가장 앞문자 Y의 주소 값이 str2에 반환되어 저장된다
- (이때 배열 이름인 str1은 상수, str2는 포인터 변수 이므로 다른 위치를 가리킬 수 있다. 따라서 다시 str2 = "abc" 선언시 Your String 은 변함이 없고, 새로 자동 할당된 문자열 abc의 a위치를 str2가 가리키게 된다!!)
- 어디서든 선언할 수 있는 상수 형태의 문자열
- char* str = "abc"; // char* str = 0x1234;(a의 주소)
- 이때 printf(0x1234); 선언 시 abc가 출력된다 즉 printf()는 문자열의 주소 값을 전달받는 함수 이다!
- ex) WhoAreYou("Hong"); // void WhoAreYou(char* str) { }
- "큰따옴표로 묶여서 표현되는 문자열은 그 형태에 상관없이 메모리 공간에 저장된 후 그 주소 값이 반환된다"
- 두 가지 형태의 문자열 표현
- 포인터 변수로 이뤄진 배열 :포인터 배열
- 포인터 배열의 이해
- 지금까지는 기본 자료형의 변수를 요소로 지니는 배열만 선언해왔지만, 포인터 변수도 변수이니 배열로 선언할 수 있다
- ex) int* arr1[20]; // 길이가 20인 int형 포인터 배열 arr1
- ex) int num1=10, num2=20, num3=30;, int* arr[3] = {&num1, &num2, &num3};
- 이렇듯 포인터 배열도 기본 자료형 배열과 다르지 않다. 다만 주소 값을 저장할 수 있도록 포인터 변수를 대상으로 선언된 배열 일 뿐이다
- 문자열을 저장하는 포인터 배열
- ex) char* strArr[3] = {"Simple", "String", "Array"};
- char* strArr[3] = {0x1004, 0x1048, 0x2012}; 형태 이다// 임의의 주소 값
- "큰따옴표로 묶여서 표현되는 문자열은 그 형태에 상관없이 메모리 공간에 저장된 후 그 주소 값이 반환된다"
- 포인터 배열의 이해
Chapter4. 포인터와 함수에 대한 이해
- 함수의 인자로 배열 전달하기
- 인자전달의 기본 방식은 '복사'이다
- 함수호출시 전달되는 인자는 인자에 저장된 '값'이 매개변수에 복사가 된다
- 따라서 인자와 매개변수는 별개이며, 매개변수가 바뀐다고 인자에 영향을 미치지 않는다!
- 배열을 함수의 인자로 전달하는 방식
- 매개변수로 배열을 선언할 수 없다! 따라서 배열의 주소를 매개변수로 선언해서 인자값으로 전달해야 한다
- ex) int arr[3] = {1, 2, 3};, int* ptr = arr;
- void SimpleFunc(int* param) { }
- void SimpleFunc(int param[]) { } // 둘은 완전히 동일한 선언이다
- 이때 매개변수 값을 변경시, 메모리의 주소 값을 매개변수로 받았으므로 실제 인자값도 변한다!
- cf) 함수 내에서 인자로 받은 배열의 길이는 계산할 수 없다. 따라서 필요시 길이 또한 매개변수로 설정해서 전달받을것!
- 인자전달의 기본 방식은 '복사'이다
- ★Call-by-value vs. Call-by-reference★
- 값을 전달하는 형태의 함수호출:Call-by-value
- 지금까지 했던 함수의 호출 방법
- 인자의 값을 변경할 수 없다
- ex) call-by-value 형태로 swap 함수 생성시 문제점
- 주소 값을 전달하는 형태의 함수호출:Call-by-reference
- 주소 값으로 접근하기 때문에 인자의 값을 변경할 수 있다
- ex) call-by-reference 형태로 swap 함수 생성
- 이젠 scanf 함수 호출시 연산자& 사용 이유를 알 수 있다
- 함수로 입력받은 인자값을 변경하기 위해 call-by-reference로 접근해야하기 때문에 주소 값을 받는다
- 문자열 입력시는 변수이름 자체가 배열의 주소 값이기 때문이다!
- 값을 전달하는 형태의 함수호출:Call-by-value
- 포인터 대상의 const 선언
- 포인터 변수가 참조하는 대상의 변경을 허용하지 않는 const 선언
- ex) const int* ptr = #
- const 선언의 위치가 맨 앞부분일 경우 포인터 변수 ptr을 대상
- "포인터 변수 ptr을 이용해서 ptr이 가리키는 변수에 저장된 값을 변경하는 것을 허용하지 않음!
- *ptr = 30; 불가능// ptr=&age; // 가능, num = 30; // 가능
- (const 선언은 상수로 만드는 선언이 아니라 변경불가의 상태로 만드는 것!)
- const 선언된 포인터 변수의 *연산을 불가능 하게 함
- 포인터 변수의 상수화
- ex) int* const ptr = #
- 주소 값이 저장되면 그 주소 값의 변경이 불가능 해 진다
- *ptr = 30; // 가능, ptr=&age; // 불가능, num = 30; // 가능
- 두 형태의 const 선언 동시에 가능
- const int* const ptr = #
- *ptr = 30; // 불가능, ptr=&age; // 불가능, num = 30; // 가능
- 포인터 변수가 참조하는 대상의 변경을 허용하지 않는 const 선언
'IT공부 > 윤성우 열혈 C프로그래밍' 카테고리의 다른 글
포인터와 배열의 시작_4 (0) | 2022.02.07 |
---|---|
포인터와 배열의 시작_3 (0) | 2022.02.05 |
포인터와 배열의 시작_1 (0) | 2022.02.02 |
C언어의 기본_4 (0) | 2022.01.29 |
C언어의 기본_3 (0) | 2022.01.26 |