프로그래밍/C++

[C++] 1차원 배열, 배열 포인터, 배열 초기화, 배열 매개변수

FORHAPPy 2021. 9. 24. 13:45

배열의 기본형태

자료형 변수명[원소갯수] = 초기값

 

배열 : 배열(array)이란 연관된 데이터를 모아서 통으로 관리하기 위해서 사용하는 데이터 타입이다. 변수가 하나의 데이터를 저장하기 위한 것이라면 배열은 여러 개의 데이터를 하나의 변수에 저장하기 위한 것이라고 할 수 있다.

여러 개의 데이터를 하나의 변수에 담아서 관리할 수 있는 방법

 

 

 

배열의 초기화

 int iArr1[5] = {};   모두 0초기화 
int iArr2[5] = {1,2,3,4,5};  각 원소에 값 삽입형태 좌측부터 0번째 배열에 값이 삽입
 int iArr3[5] = {1,2,3};  채우지 않은 부분은 각 전부 0 초기화 
int iArr4[] = {1,};  배열 크기가 5개라고 인식하지 못함. 배열 갯수 1개로 인식
int iArr5[] = {1,2,3,4,5}; 배열의 크기를 명시하지 않으면 초기화 하는 원소의 갯수로 배열의 크기가 결정
int iArr[] = {};  크기를 모르기 때문에 불가능

배열의 원래 이름은 정적 배열이기 때문에 애초에 컴파일 시점에서 배열의 크기가 결정된다.

따라서 배열을 선언할 시에 반드시 상수가 와야한다. 

런타임(프로그램 실행중) 시점에 값이 바뀔 수도 있기 때문이다.

 

const를 붙여주면 사용가능 하다.
const int iSize = 25;
const int* ptr = &iSize; 

 

 

<배열 크기 부분에 변수를 사용했을 시 불가능>

 

<const 붙인 변수는 상수화가 되어서 가능>

 

 

<원소 접근시에는 변수를 사용가능>

 

 

 

배열의 크기

배열의 크기 
int iArr[5] = { }; 


배열의 이름을 sizeof로 돌려보면 배열의 전체적인 크기가 나온다. 
cout << sizeof(iArr) << endl;  

크기가 4바이트 만큼 5공간 즉, 20바이트가 나온다.


원소 하나의 크기를 확인해보면 원소 하나의 크기가 나온다. 
cout << sizeof(iArr[0]) << endl;

 

 

 

배열과 포인터와의 관계.


배열의 이름은 배열의 시작 주소를 가리키는 상수 포인터이다 
따라서 포인터로 넘겨줄때 그냥 배열 이름 그대로 넘겨주면 된다.

 

 

 

 

포인터 연산

  포인터 연산은 기본적으로 더하기 혹은 빼기만 제공된다. 

다른 연산을 할 경우 주소가 어딜 가리키고 있을지 모르기 때문에 미리 막아뒀다.


포인터연산을 주로 사용하는 경우는 일반 변수가 아닌 주로 배열일 경우 사용이 된다.

포인터 연산은 반드시 연속된 메모리 공간에 할당된 데이터를 대상으로 수행해야 옳다. 

 

 int iArr[5] = { 1,2,3,4,5 };  두 연산은 기본적으로 같아보이지만 다르다. 즉, iArr + 1 와 iArr += 1는 다르다.
cout << *(iArr + 1) << endl;  값을 대입하지 않은 순수 더해서 간 위치
 cout << (iArr += 1) << endl;  iArr = iArr + 1 (대입)이 형태는 값을 바꾼다는 말

 

 

포인터 연산의 형태

 인덱스 연산 = 포인터 연산

cout << *(iArr + 1) << endl; 포인터 연산
cout << iArr[1] << endl; 인덱스 연산

 


포인터 연산은 절대 포인터 크기만큼 이동하는 것이 아닌 현재 자료형의 크기만큼 움직인다

더보기

배열의 이름은 배열의 시작 주소를 가리키는 상수 포인터이다 (다시 한번 강조)

= 배열의 이름은 바꿀수 없는 포인터다

= 배열의 이름은 제일 첫번째 원소를 가리키는 상수 포인터

 

 

따라서 아래 노란 형관펜의 연산은 불가능하다.

 

 

 

함수에서 배열을 매개변수로 받기 1

iSize 대신 상수를 쓰는건 안좋은 습관이다. 

변경사항이 생길 경우 하나만 바꿔줘도 될 것을 전체를 일일이 수정해야 하기 때문이다.

따라서 위 그림처럼 상수대신 iSize라는 새로운 변수를 만드는 방법이 있다.

iSize 대신 직접 sizeof 연산자를 사용해도 되고

전역변수로 iSize = 7; 을 선언하는거도 방법이다. 

#define 이나 enum 을 사용해도 된다.

 

 

 

함수에서 배열을 매개변수로 받기 2

지금 매개변수 형태는 ( int ptr[ ] ) ,  ( int* ptr )  이런식으로 배열을 받을 수있다.

중요한건 둘 가지 경우 다 배열만을 받을 수 있는 포인터가 아닌 일반 변수의 주솟값도 받을 수 있다.

 ( int ptr[ ] ) 형태로 써줄 경우에는  배열의 주솟값을 받겠다는걸 명시적으로 알 수 있다.

 

그러나, 배열의 주소값을 받겠다라고 명시적으로 표현할 뿐이지  무조건 배열의 주소만 받겠다 라는 뜻은 아니다.

이역시 일반 변수의 주솟값도 받을 수 있다.

더보기

위에 인자에서 이런 형태 (int ptr[])로 매개변수를 정의했으나
main 함수 안에서도 저렇게 포인터 변수를 만들수 있다 착각하지 마라.

int ptr[] = nullptr;  이렇게 안됨