본문 바로가기

C++ IDE를 위한 과정

C++ 포인터 AND 동적배열

728x90
반응형

지금까지 정적인 변수와 배열만 사용하였으니 입력해서 배열을 받는 동적배열과

C++에서는 몰라서는 안되는 포인터의 개념과 활용방법을 같이 학습해 봅시다.


포인터

  • 메모리의 주소를 저장하는 변수
  • 포인터 변수는 *을 이용하여 선언
// 포인터 예시
int main(){
    int *pointer;
    int num = 10;

    pointer = &num // pointer에 num의 메모리 주소를 저장함.

    std::cout << pointer << std::endl;
    //pointer에는 num의 주소값이 저장되어 있음 8bit 형식
    
    std::cout << *pointer << std::endl;
    //*pointer는 주소값에 저장되어 있는 실제 값에 접근 ==> 10출력
}

 

실습. pointer 사용해보가

  • 만약 num의 값을 20으로 다시 할당 한다면, pointer와 *pointer의 값은 어떻게 될지 확인해 보시오.
  • pointer를 이용하여 num의 값을 변경가능한지 확인해 보시오.
    •  
using namespace std;

int main() {

	int num = 10;

	int* p = NULL; // 포인터 주소값 초기화

	p = &num;
	cout << "포인트 p가 가리키는 값 : " << p << endl;
	cout << "num 의 값              : " << num << endl;

	num = 20;
	cout << "포인트 p가 가리키는 값 : " << p << endl;
	cout << "포인트 p가 가리키는 값 : " << *p << endl;
	cout << "num 의 값              : " << num << endl;

	(*p)++; // **num++
	cout << "포인트 p가 가리키는 값 : " << *p << endl;
	cout << "num 의 값 
}

  • 위 결과를 보면 값은 10 -> 20으로 변경 되었지만, 주소값은 변화가 없다는 것을 확인가능하다.
    • 무엇을 알수 있는냐?
    • 값이 변화였는데 메모리 주소가 변경되지 않았다는것은 포인터를 활용하여 효율적으로 변수를 사용할 수있단느 것을 뜻한다.
    • 예를 들어 {10, 20 ,30}의 배열이 존재할때 10,20,30의 주소값은 다 다르다. 파이썬에서는 P[0][1]의 형식으로 값을 때왔었지만, 우리는 주소값을 다룰 수 있으므로 포인터를 활용하여 간단하게 호출이 가능하다는 것을 알 수 있다.
  • 주의사항은 (*p)++처럼 ++와 같은 기본 제공연산자와 같은 기능을 사용할때는 우선순위를 잘 알아야한다. 만약 ( )없이 *p++를 사용할 시 p++의 대한 주소 값이 생성되므로, 원하는 메모리에 할당된 값이 생성되지 않음을 주의해야 한다. (아래 사이트 참조)
 

C++ 기본 제공 연산자, 우선 순위 및 결합성

자세한 정보: C++ 기본 제공 연산자, 우선 순위 및 결합성

learn.microsoft.com

 

 


변수와 메모리

포인터는 메모리와 변수에 밀접한 관계를 넘어거 그냥 변수와 매모리 그자체 이므로 필히 개념을 알고 있어야 됩니다.

  • 예시 : int data = 100;
    • int : 4byte
    • data : 식별자
    • 100 : 데이터
  • 저장되는 메모리 구역은 변수 선언 위치에 따라 다름 - 컴파일러가 심볼테이블을 참조
  • 변수는 데이터를 필요할 때 메모리에서 찾을 수 있게, 주소 정보를 포함하고 있어야 하며 메모리에 차지하는 용량의 정보도  필요함

  • 그림에서와 같이 int는 4byte이므로 32비트의 최대 인수 2^31 까지만 받을 수 있다.
    • + -의 정수를 합쳐서 2^32의 개수를 입력 받기에 2^31하고도 -1의 값이 최대가 되는 것이다.
    • 만약 그 값이 넘어갈경우 가장 낮은 값으로 넘어간다.

  • 이 처럼 duble, float, string, char에도 각각 할당된 크기가 있기에 주의하면서 사용하여야 된다.

실습. 포인터 사용해보기

  • chaf, int, float 형 변수를 각각 하나씩 만들고
  • 포인터를 이용해서 값을 1씩 더하거나 빼는 함수를 각 자료형 마다 하나씩 만들고 main함수에서 출력하시오.

출력 예시

using namespace std;

int main(){
	char ch = 'A';
    int i = 10;
    float f = 5.5;
    
    (*ch)++; //아스키코드 값에 크기가 변경
    (*i)++;
    (*f)++;
    cout << "char 증가후 : " << ch << endl;
    cout << "int 증가후 : " << i << endl;
    cout << "float 증가후 : " << f << endl;
    
    (*ch)--; // 아스키코드 값에 크기가 변경
    (*i)--;
    (*f)--;
    
    cout << "char 감소후 : " << ch << endl;
    cout << "int 감소후 : " << i << endl;
    cout << "float 감소후 : " << f << endl;
    
}

동적 배열(선언과 할당)

  • 배열의 크기를 정하고 사용하지 않고 후에 선언하는 배열을 동적 배열이라고 함
  • 동적 배열을 만들기 위해선 포인터 변수와 new키워드 사용.
// 동적 배열 예시
int main(){
    int n2;
    std::cout << "숫자를 입력하세요 : ";
    std::cin >> n2;
    
    int *arr = new int[n2]; 
    //실행중에 배열크기가 선언 되므로 포인터 필요
    //new라는 키워드를 사용하여 동적 배열 할당    
}

동적 배열(사용과 해제(반납))

  • 동적 배열을 해제(반납)하기 위해선 delete 키워드 사용.
int main(){
	int n2;
    std::cout << "숫자를 입력하세요 : ";
    std::cin >> n2;
    
    int *arr = new int[n2]; // 동적 배열 선언 및 할당
    
    for (int i = 0; i < n2; i++){
    	arr[i] = i+1; // 동적 배열 사용
    }
    
    delete[] arr;// 동적 배열 해제(반납), 동적 메모리는 사용 후 꼭 해체하기
  • 동적 배열은 실행중에 할당 되는 만큼 해제를 하지 않을경우 메모리누수가 심하게 일어나므로 꼭 사용후 해제를 진행해주어야 함

실습. 동적배열 사용해보기

  • 만들고 싶은 배열의 크기를 입력받고, 해당 배열에 값을 입력 후 출력해 보시오.

결과 예시

using namespace std;

int main(){

	int n2;
    
    int *arr = new int[n2]; // 동적 배열 선언 및 할당

    cout << "배열의 크기를 입력하세요 : ";
    cin >> n2;
    
    cout << "5개의 값을 입력하세요 : "<<endl;
    
    for(int i=0; i < n2 ; i++){
    	cout << i+1 << "번째 값: ";
        cin >> arr[i];
    }
    
    cout << "입력된 배열의 값 : ";
    for (int j = 0; j < n2; j++)
    {
        cout << arr[j] << " ";
    }
    cout << endl;
    
    delete[] arr; // 동적 배열 반납
    
    return 0;
}

동적 배열(2차원 배열)

//2차원 배열 예시

using namespace std;

int main(){
	
    int num;
    cout <<"숫자를 입력하세요: ";
    cin >> num;
    // x = 열, y = 행
    //동적 배열 선언 & 할당
    
    int **arr2 = new int *[num]; // num 크기의 포인터 배열 생성 = x 값
    
    for(int i = 0; i < num; i++){
    	arr[i] = new int[num]; // 각 행에 num 크기의 배열 할당 = y 값
    }
    
    for(int i = 0; i < num; i++){
    	for(int j = 0; j < num; j++){
        	arr2[i][j] = 0; // 동적 배열 사용
        }
    }
    
    //동적 배열 해제(반납)
    for(int i = 0; i < num ; i++){
    	delete[] arr2[i];
    }
    
    delete[] arr2;
    
    return 0;
}

 

  • 코드로 보면 어렵다고 느낄수 있을텐데요 지금 당장은 아래의 내용으로 기억하시면 됩니다.
    • 2차원 배열은 포인터 2개
    • 순서는 행 -> 열 -> 행 -> 열순서 (할당 할당 해제 해제)
    • 행(row)의 개수 먼저 선언 x 값
    • 열(기둥)(colum)의 개수 선언 y 값

실습. 2차원 동적배열 사용해보기

  1. 사용자로부터 x,y 2개의 자연수를 입력 받기
  2. 만약 사용자가 x 와 y에 0이나 음수를 입력한다면 에러 메세지를 출력 후 다시 입력 받기
  3. x  *  Y의 크기를 갖는 이차원 동적 배열 arr을 선언
  4. arr[0][0] 부터 arr[x][y] 까지 순서대로 1 부터 x * y 저장
  5. arr[0][0] 부터 arr[x][y] 까지 저장된 값 출력

해답 예시

#include <iostream>

using namespace std;

int main(){
	
    int x = 0; //초기 설정
    int y = 0; //초기 설정
    int count = 1;//할당 될 변수
    
	cout << "x를 입력하세요 : ";
	cin >> x;
	cout << "y를 입력하세요 : ";
	cin >> y;

	while (x <= 0 || y <= 0)
	{
		cout << "x와 y모두 양수를 입력해주세요." << endl;
		cout << "x를 입력하세요 : ";
		cin >> x;
		cout << "y를 입력하세요 : ";
		cin >> y;
	}
    
    //동적 배열 선언 & 할당
    int **arr2 = new int *[x]; // 행 포인트 배열 생성
    
    for(int i = 0, i < x; i++){
    	arr[i] = new int[y]; // 열 배열 생성
    }
    // 할당
    for(int i = 0; i < x; i++){
    	for(int j = 0; j < y; j++){
        	arr2[i][j] = count;
            count++;
        }
    }
    
    //출력
    for (int i = 0; i < x; i++){
		for (int j = 0; j < y; j++){
			cout << arr2[i][j] << " ";
		}
		cout << endl;
	}
    for(int i = 0; i < x ; i++){
    	delete[] arr2[i]; //행 해제
    }
    delete[] arr2; // 열 해제
    
    return 0;
}

 

중요한 내용이다 보니 분량이 많습니다. 그러니 차근차근 읽어 보시고 이해하시길 바랍니다.

오늘도 같이 공부하시느라 수고 많으셨습니다!!!!!!

반응형

'C++ IDE를 위한 과정' 카테고리의 다른 글

C++ 문자열 포인터  (0) 2025.03.13
C++ call by 기능  (0) 2025.02.24
C++ namspace  (0) 2025.02.21
C++ 구조체 VS 클래스, getter setter, 상속  (0) 2025.02.12
C++ 클래스 & this pointer  (0) 2025.02.11