Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 7: 포인터Topic 3: 포인터 연산과 배열

Topic 3: 포인터와 배열 🎯

🎯 학습 목표

  • 포인터와 배열의 관계를 깊이 이해할 수 있다
  • 포인터 산술 연산을 활용할 수 있다
  • 2차원 배열과 포인터를 다룰 수 있다
  • C-스타일 문자열을 포인터로 처리할 수 있다

📖 포인터와 배열의 관계

배열 이름은 첫 번째 요소를 가리키는 포인터와 같은 역할을 합니다.

아날로지: 아파트 주소와 같습니다.

  • 배열 이름: 아파트 전체 주소 (101동)
  • 포인터: 특정 호수 주소 (101동 501호)
  • 인덱스: 층과 호수 번호

🔍 기본 관계 이해

#include <iostream> using namespace std; int main() { int arr[5] = {10, 20, 30, 40, 50}; int* ptr = arr; // arr는 &arr[0]과 동일 cout << "=== 배열과 포인터의 관계 ===" << endl; cout << "arr 주소: " << arr << endl; cout << "&arr[0] 주소: " << &arr[0] << endl; cout << "ptr 주소: " << ptr << endl; // 모두 같은 값 cout << "\n=== 첫 번째 요소 접근 ===" << endl; cout << "arr[0]: " << arr[0] << endl; cout << "*arr: " << *arr << endl; cout << "*ptr: " << *ptr << endl; cout << "*(arr + 0): " << *(arr + 0) << endl; return 0; }

배열 요소 접근 방법들

#include <iostream> using namespace std; int main() { int numbers[4] = {100, 200, 300, 400}; int* p = numbers; cout << "=== 다양한 접근 방법 ===" << endl; for(int i = 0; i < 4; i++) { cout << "인덱스 " << i << ":" << endl; cout << " 배열 표기법: numbers[" << i << "] = " << numbers[i] << endl; cout << " 포인터 표기법: *(numbers + " << i << ") = " << *(numbers + i) << endl; cout << " 포인터 변수: *(p + " << i << ") = " << *(p + i) << endl; cout << " 포인터 인덱스: p[" << i << "] = " << p[i] << endl; cout << endl; } return 0; }

🔢 포인터 산술 연산

포인터 산술 연산은 배열 순회와 메모리 탐색의 핵심입니다.

기본 산술 연산

#include <iostream> using namespace std; int main() { double data[6] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6}; double* ptr = data; cout << "=== 포인터 산술 연산 ===" << endl; cout << "double 크기: " << sizeof(double) << " 바이트" << endl; cout << "배열 시작 주소: " << ptr << endl; // 포인터 증가 for(int i = 0; i < 6; i++) { cout << "ptr + " << i << ": 주소=" << (ptr + i) << ", 값=" << *(ptr + i) << endl; } // 포인터 간 차이 double* end = data + 5; cout << "\n포인터 간 차이: " << (end - ptr) << " 요소" << endl; return 0; }

포인터로 배열 순회

#include <iostream> #include <iomanip> using namespace std; int main() { int scores[8] = {85, 92, 78, 96, 88, 75, 91, 83}; int* current = scores; int* end = scores + 8; cout << "=== 포인터로 배열 순회 ===" << endl; // 방법 1: 인덱스 사용 cout << "방법 1 (인덱스):" << endl; for(int i = 0; i < 8; i++) { cout << setw(3) << current[i] << " "; } cout << endl; // 방법 2: 포인터 증가 cout << "방법 2 (포인터 증가):" << endl; current = scores; // 포인터 재설정 for(int i = 0; i < 8; i++, current++) { cout << setw(3) << *current << " "; } cout << endl; // 방법 3: 포인터 비교 cout << "방법 3 (포인터 비교):" << endl; current = scores; // 포인터 재설정 while(current < end) { cout << setw(3) << *current << " "; current++; } cout << endl; return 0; }

📊 2차원 배열과 포인터

2차원 배열은 포인터의 포인터로 이해할 수 있습니다.

2차원 배열 기초

#include <iostream> #include <iomanip> using namespace std; int main() { int matrix[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; cout << "=== 2차원 배열과 포인터 ===" << endl; // 2차원 배열 출력 cout << "배열 인덱스 방법:" << endl; for(int i = 0; i < 3; i++) { for(int j = 0; j < 4; j++) { cout << setw(3) << matrix[i][j] << " "; } cout << endl; } // 포인터 방법 cout << "\n포인터 방법:" << endl; int* ptr = matrix[0]; // 첫 번째 행의 첫 번째 요소 for(int i = 0; i < 12; i++) { cout << setw(3) << *(ptr + i) << " "; if((i + 1) % 4 == 0) cout << endl; } return 0; }

행 포인터 사용

#include <iostream> #include <iomanip> using namespace std; int main() { int table[4][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90}, {100, 110, 120} }; cout << "=== 행 포인터 사용 ===" << endl; // 각 행을 포인터로 처리 for(int row = 0; row < 4; row++) { int* rowPtr = table[row]; // 행의 첫 번째 요소 포인터 cout << "행 " << row << ": "; for(int col = 0; col < 3; col++) { cout << setw(4) << *(rowPtr + col) << " "; } // 행의 합계 계산 int sum = 0; for(int col = 0; col < 3; col++) { sum += *(rowPtr + col); } cout << "| 합계: " << sum << endl; } return 0; }

📝 C-스타일 문자열과 포인터

C-스타일 문자열은 char 배열이며, 포인터로 효율적으로 처리할 수 있습니다.

문자열 기본 조작

#include <iostream> #include <cstring> using namespace std; int main() { // 다양한 문자열 선언 방법 char str1[] = "Hello"; // 배열 char str2[20] = "World"; // 고정 크기 배열 const char* str3 = "C++"; // 포인터 (문자열 리터럴) cout << "=== 문자열과 포인터 ===" << endl; cout << "str1: " << str1 << " (크기: " << sizeof(str1) << ")" << endl; cout << "str2: " << str2 << " (크기: " << sizeof(str2) << ")" << endl; cout << "str3: " << str3 << " (크기: " << sizeof(str3) << ")" << endl; // 문자열 길이 계산 (포인터 사용) const char* text = "Programming"; int length = 0; const char* ptr = text; while(*ptr != '\0') { length++; ptr++; } cout << "\n문자열 \"" << text << "\"의 길이: " << length << endl; cout << "strlen() 결과: " << strlen(text) << endl; return 0; }

문자열 처리 함수 구현

#include <iostream> using namespace std; // 문자열 길이 계산 int myStrlen(const char* str) { int length = 0; while(*str++) { length++; } return length; } // 문자열 복사 void myStrcpy(char* dest, const char* src) { while(*src) { *dest++ = *src++; } *dest = '\0'; // 널 문자 추가 } // 문자열 비교 int myStrcmp(const char* str1, const char* str2) { while(*str1 && (*str1 == *str2)) { str1++; str2++; } return *str1 - *str2; } // 문자열 연결 void myStrcat(char* dest, const char* src) { // dest의 끝으로 이동 while(*dest) { dest++; } // src를 dest 끝에 복사 while(*src) { *dest++ = *src++; } *dest = '\0'; } int main() { char buffer[100]; const char* source = "Hello, World!"; cout << "=== 사용자 정의 문자열 함수 ===" << endl; // 문자열 복사 myStrcpy(buffer, source); cout << "복사된 문자열: " << buffer << endl; cout << "길이: " << myStrlen(buffer) << endl; // 문자열 연결 myStrcat(buffer, " Welcome to C++!"); cout << "연결된 문자열: " << buffer << endl; // 문자열 비교 const char* str1 = "apple"; const char* str2 = "banana"; int result = myStrcmp(str1, str2); cout << "\n\"" << str1 << "\"\"" << str2 << "\" 비교: "; if(result < 0) { cout << "첫 번째가 사전상 앞섬" << endl; } else if(result > 0) { cout << "두 번째가 사전상 앞섬" << endl; } else { cout << "두 문자열이 같음" << endl; } return 0; }

🎯 실습: 간단한 동적 문자열

#include <iostream> #include <cstring> using namespace std; // 문자열을 동적으로 복사하는 함수 char* copyString(const char* source) { // 문자열 길이 계산 int len = strlen(source); // 동적 메모리 할당 (+1은 null 문자를 위함) char* copy = new char[len + 1]; // 문자열 복사 strcpy(copy, source); cout << "\"" << source << "\"를 복사했습니다. (길이: " << len << ")" << endl; return copy; } // 문자열 연결 함수 char* concatenateStrings(const char* str1, const char* str2) { int len1 = strlen(str1); int len2 = strlen(str2); // 두 문자열을 합칠 공간 할당 char* result = new char[len1 + len2 + 1]; // 첫 번째 문자열 복사 strcpy(result, str1); // 두 번째 문자열 연결 strcat(result, str2); return result; } int main() { cout << "=== 동적 문자열 처리 ===" << endl; const char* original = "Hello"; const char* world = " World!"; // 문자열 복사 char* copy = copyString(original); cout << "복사된 문자열: " << copy << endl; // 문자엱 연결 char* combined = concatenateStrings(original, world); cout << "연결된 문자열: " << combined << endl; // 메모리 해제 delete[] copy; delete[] combined; cout << "\n모든 메모리가 해제되었습니다." << endl; return 0; }

🎯 실습: 문자열 기본 처리

#include <iostream> #include <cstring> using namespace std; // 문자열 길이 계산 (포인터 사용) int stringLength(const char* str) { int length = 0; while(*str != '\0') { // null 문자까지 length++; str++; // 포인터 증가 } return length; } // 문자열 복사 함수 void copyString(char* dest, const char* src) { while(*src != '\0') { *dest = *src; // 문자 복사 dest++; src++; } *dest = '\0'; // null 문자 추가 } // 문자열 대문자로 변환 void toUpperCase(char* str) { while(*str != '\0') { if(*str >= 'a' && *str <= 'z') { *str = *str - 32; // 대문자로 변환 } str++; } } int main() { cout << "=== 포인터로 문자열 처리 ===" << endl; const char* original = "hello world"; char buffer[50]; // 문자열 길이 계산 int len = stringLength(original); cout << "\"" << original << "\"의 길이: " << len << endl; // 문자열 복사 copyString(buffer, original); cout << "복사된 문자열: " << buffer << endl; // 대문자로 변환 toUpperCase(buffer); cout << "대문자 변환: " << buffer << endl; return 0; }

💡 모범 사례와 주의사항

✅ 좋은 습관

  1. 배열 경계 확인

    int arr[5]; int* ptr = arr; for(int i = 0; i < 5; i++) { // 경계 체크 cout << *(ptr + i) << endl; }
  2. const 포인터 활용

    void printArray(const int* arr, int size) { for(int i = 0; i < size; i++) { cout << arr[i] << " "; // 수정 불가 } }
  3. 널 포인터 체크

    void safeStringLength(const char* str) { if(str != nullptr) { cout << "길이: " << strlen(str) << endl; } }

❌ 피해야 할 실수

  1. 배열 경계 초과

    int arr[3] = {1, 2, 3}; int* ptr = arr; cout << *(ptr + 5); // 위험한 접근!
  2. 문자열 리터럴 수정

    const char* str = "Hello"; // str[0] = 'h'; // 오류! 리터럴 수정 불가
  3. 포인터 산술 오류

    int* ptr1 = new int(10); int* ptr2 = new int(20); // int diff = ptr2 - ptr1; // 의미없는 연산

🔍 성능 최적화 팁

#include <iostream> #include <chrono> using namespace std; using namespace std::chrono; void arrayIndexAccess(int* arr, int size) { int sum = 0; for(int i = 0; i < size; i++) { sum += arr[i]; // 인덱스 접근 } } void pointerArithmetic(int* arr, int size) { int sum = 0; int* end = arr + size; while(arr < end) { sum += *arr++; // 포인터 증가 } } int main() { const int SIZE = 1000000; int* bigArray = new int[SIZE]; // 배열 초기화 for(int i = 0; i < SIZE; i++) { bigArray[i] = i; } // 인덱스 접근 시간 측정 auto start = high_resolution_clock::now(); arrayIndexAccess(bigArray, SIZE); auto end = high_resolution_clock::now(); auto indexTime = duration_cast<microseconds>(end - start); // 포인터 산술 시간 측정 start = high_resolution_clock::now(); pointerArithmetic(bigArray, SIZE); end = high_resolution_clock::now(); auto pointerTime = duration_cast<microseconds>(end - start); cout << "=== 성능 비교 (배열 크기: " << SIZE << ") ===" << endl; cout << "인덱스 접근: " << indexTime.count() << " microseconds" << endl; cout << "포인터 산술: " << pointerTime.count() << " microseconds" << endl; delete[] bigArray; return 0; }
Last updated on