Developer

16.(C언어) 배열 본문

Programming Language/C

16.(C언어) 배열

DPhater 2020. 8. 1. 21:30

배열은 같은 자료형의 변수가 여러개 필요할때 변수 선언과 관리 및 처리를 쉽게 도와준다.

#include<stdio.h>
int main(){
	int arr[10]; //크기가 10인 int형 배열 선언 
	int arr1[10]={1,2,3,4,5,6,7,8,9,10};  //선언 및 초기화 
	
	arr[0]=1; //arr배열의 0번 위치에 1을 저장 
	arr[1]=2;
	arr[2]=3;
	
	printf("%d\n",arr[0]);
	printf("%d\n",arr[1]);
	printf("%d\n",arr[2]);
	
	
	printf("%d\n",arr1[0]);
	printf("%d\n",arr1[7]);
	printf("%d\n",arr1[9]);
	return 0;
}

코드1 실행 결과

위의 코드를 보면 대략적인 사용 방법을 알 수 있을 것이다.

배열은 자료형 배열이름[크기]; 의 형식으로 선언하고

배열의 초기화는 자료형 배열이름[크기]={값,값,값,값...}; 과 같이 중괄호를 사용한다.

또는 배열의 크기를 생략할 수 도 있다. 대신 이러한 경우 초기화를 반드시 해줘야한다. 자료형 배열이름[]={값,값}; 크기없이 배열을 선언해 초기화 하면 초기화해준 값의 갯수만큼 배열이 생성된다.

코드1에서는 초기화 하지않고 선언한 배열 arr과 초기화를 해준 arr1 두 가지 배열이 존재한다.

선언된 두 가지 배열의 모습이다. 각 배열의 위에 쓰여있는 숫자는 배열의 index로 배열의 각 요소를 접근할 때 index를 사용한다. 주의할점은 배열의 index는 0부터 시작한다는 것이다.

arr1[3]은 arr1배열의 4번째 요소인 4이다. arr[index]를 사용해 해당 요소의 값을 사용하거나 변경할 수 있다.

그리고 초기화할 때에는 각 요소를 중괄호를 사용해 초기화할 수 있지만 초기화하지 않은 배열은 각 요소에 직접 입력을 해줘야 한다. 초기화 되지 않은 배열에는 쓰레기값이 들어있다. 그렇기 때문에 초기화 되지 않은 배열을 사용할 때 주의해야한다.

배열 초기화 특성

배열을 초기화 할 때 중괄호에 크기만큼 갯수를 입력하지 않으면 남은 공간은 모두 0이 저장된다.

#include<stdio.h>
int main(){
	int i;
	int arr[10]={1,};	
	for(i=0;i<10;i++){
		printf("%d  ",arr[i]);
	} 
	return 0;
}

코드2 실행 결과

코드2에서는 크기 10의 int형 배열을 선언한뒤 중괄호로 첫번째 index만 1로 초기화 하고 나머지는 입력하지 않았다.

이러한 경우 남은 요소는 모두 0이 된다. 만약 첫번째 요소에 0을 넣으면 간편하게 모든 요소를 0으로 초기화 할 수 있다.

코드2 에서는 반복문을 통해 배열의 각 요소들을 출력하고있다. 배열은 연속으로 배정된 저장공간이므로 반복문을 사용하면 편하게 이용할 수 있다.

배열과 반복문

코드2 처럼 배열은 반복문을 사용하면 편하게 이용할 수 있다.

scanf를 사용해 10개의 정수를 배열에 저장하고, 배열의 저장된 10개의 정수의 합을 구하는 코드를 작성해 보자.

#include<stdio.h>
int main(){
	int i,sum=0;         //sum 은 값을 누적하기 위한 변수 
	int arr[10]; 
	
	for(i=0;i<10;i++)          //배열의 크기만큼 반복하면서  
		scanf("%d",&arr[i]);   //배열의 요소에 입력된값으 저장 
	
	for(i=0;i<10;i++)  
		sum+=arr[i];     //sum=sum+arr[i] 배열의 요소들을 더한다. 
		
	printf("%d\n",sum);
	
	return 0;
}

코드3 실행 결과

1부터 0까지 입력해서 배열에 저장하고 배열의 값들을 합친 55가 출력되었다.

여기에서 만약 더 많은 입력을 하고싶어서 배열의 크기를 20으로 바꾸었다고 생각해보자!

#include<stdio.h>
int main(){
	int i,sum=0;         //sum 은 값을 누적하기 위한 변수 
	int arr[20]; 
	
	for(i=0;i<20;i++)          //배열의 크기만큼 반복하면서  
		scanf("%d",&arr[i]);   //배열의 요소에 입력된값으 저장 
	
	for(i=0;i<10;i++)  //이 부분을 깜빡해서 못바꿨다고 생각하자
		sum+=arr[i];     
		
	printf("%d\n",sum);
	
	return 0;
}

코드4 실행 결과

코드4는 배열의 크기를 늘리고 입력을 받기 위한 반복문도 정상적으로 변경해 주었지만 합계를 구하는 반복문의 조건식을 깜박하고 바꾸지않아 0~9번까지의 요소들만 합쳐진 것이다. 이러한 실수를 방지하기 위해 반복문의 조건문을 배열의 크기로 작성할 수 있다

#include<stdio.h>
int main(){
	int arr[20]; 
	printf("%d",sizeof(arr));
    return 0;
}

코드5 실행 결과

배열의 크기도 sizeof로 구할 수 있다. 그런데 결과가 원하는 20이 아닌 80이 나왔다. 왜냐하면 arr은 int형 변수가 20개 선언된것이므로 int형의 크기인 4byte*20인 80이 나온것이다. 그럼 배열의 요소 갯수를 알기 위해서는 int형의 크기인 4로 나누어주면 된다.

#include<stdio.h>
int main(){
	int arr[20]; 
	printf("%d",sizeof(arr)/sizeof(int));
	return 0;
}

코드6 실행 결과

원하는 값인 20이 나온것을 확인할 수 있다. 이제 아까 실수한 코드에 적용해보자.

#include<stdio.h>
int main(){
	int i,sum=0;        
	int arr[20]; 
	
	for(i=0;i<sizeof(arr)/sizeof(int);i++)          
		scanf("%d",&arr[i]);   
	
	for(i=0;i<sizeof(arr)/sizeof(int);i++)  
		sum+=arr[i];     
		
	printf("%d\n",sum);
	
	return 0;
}

이제 배열의 크기를 바꾸어도 반복횟수는 변경해주지 않아도 된다.

2차원 배열

2차원 배열은 가로x세로 형태로 이루어져 있다고 생각하면된다.

생각만 그렇게 하는것이지 실제 메모리에 가로x세로 형태로 메모리를 차지하지는 않는다.

2차원 배열의 선언은 대괄호 두개를 사용한다.

2차원 배열의 선언: 자료형 배열이름[세로크기][가로크기];

2차원 배열의 초기화: 자료형 배열이름[세로크기][가로크기]{ {값, 값}, {값, 값}};

초기화에서 내부의 작은 중괄호의 갯수는 세로 크기를 넘으면 안되고, 작은 중괄호 안의 값은 가로크기를 넘어서는 안된다.

#include<stdio.h>
int main(){
	int arr[4][3];
	
	int col=sizeof(arr[0])/sizeof(int);
	int row=sizeof(arr)/sizeof(arr[0]);
	
	int i,j;
	for(i=0;i<row;i++){
		for(j=0;j<col;j++){
			scanf("%d",&arr[i][j]);
		}
	}
	
	
	for(i=0;i<row;i++){
		for(j=0;j<col;j++){
			printf("%d  ",arr[i][j]);
		}printf("\n");
    }
}

코드7 실행 결과

2차원 배열도 1차원 배열과 똑같이 생각하면 된다.

row와 col을 계산하는 곳을 보자

-col계산

sizeof(arr[0])는 배열의 0번 행의 크기를 말한다.

가로 한줄의 크기를 말하는데 이를 int로 나누어주면 한줄에 몇개의 요소가 있는지 계산할 수 있다.

-row계산

sizeof(arr)의 경우 배열 전체의 크기를 말하며 전체의 크기에서 한줄의 크기를 나누어주면 세로를 구할 수 있다.

배열을 선언할 때 대괄호 수에 따라 다차원 배열을 선언할 수 있다.

배열과 포인터

배열의 이름은 해당 배열의 첫 번째 주소를 가지고 있다.

2차원 배열에 맨 마지막에 있는 그림을 예시로 들면 배열 이름 arr은 arr[0][0]의 주소를 가지고 있다.

arr[0]은 arr[0][0]의 주소

arr[1]은 arr[1][0]의 주소

arr[2]는 arr[2][0]의 주소를 가지고 있는 것이다.

그래서 포인터에 배열의 이름을 넣으면 포인터를 통해 배열에 접근이 가능하다.

#include<stdio.h>
int main(){
	int arr[10]={1,3,3,4,5,6,7,8,9,10} ;
	int *ptr;
	ptr=arr;  
	printf("%d\n",*ptr);
	printf("%d\n",ptr[4]);
	return 0;
}

코드8 실행 결과

배열의 이름에는 배열의 첫번재 요소의 주소가 들어 있으므로 ptr=arr과 같이 포인터에 할당할 수 있다.

*ptr의 경우 첫 번째 요소를 가리키고 있는 주소를 역참조 했으므로 1이 출력된다.

또한 포인터도 배열처럼 인덱스로 원하는 곳의 값을 참조할 수 있다.

#include<stdio.h>
int main(){
	int arr[10]={1,3,3,4,5,6,7,8,9,10} ;
	int *ptr;
	ptr=arr;  
	printf("%d\n",*ptr);
	printf("%d\n",*(ptr+1));
	return 0;
}

코드9 실행 결과

코드9 처럼 포인터 연산을 사용할 수도 있다. 포인터는 연산을 할경우 자료형의 크기만큼 연산이 수행된다.

쉽게 말해서 ptr은 int형 포인터이므로 1을 더하면 현재 가지고 있는 주소에서 int형의 크기인 4byte만큼 더해진다.

배열은 연속적인 메모리에 할당되므로 *(ptr+1)과 같이 사용할 수 있다.

arr[1]은 ptr[1]과 같고

arr[1]은 *(ptr+1)과 같다.

2차원 배열과 포인터

2차원 배열은 괄호 크기를 지정해 주어야한다.

#include<stdio.h>
int main(){
	int arr[4][3]={{1,2,3},
	               {4,5,6},
				   {7,8,9},
				   {10,11,12}
				   };
	int (*ptr)[3];
	ptr=arr;
	
	printf("%d\n",ptr[3][2]);
	return 0;
}

코드10 실행 결과

int (*ptr)[3]은 가로 크기 3인 배열을 가리키는 포인터라는 뜻이다. 괄호가 없는 int *ptr[3]은 int형 포인터 3개를 담을 수 있는 배열이다. 괄호가 있다면 배열을 가리키는 배열 포인터 괄호가 없다면 포인터를 여러개 담을 수 있는 포인터 배열이다.

'Programming Language > C' 카테고리의 다른 글

18.(C언어) 문자열  (0) 2020.08.01
17(C언어) 동적할당  (0) 2020.08.01
15.(C언어) 포인터  (0) 2020.08.01
14.(C언어) 반복문_for,while  (0) 2020.08.01
13.(C언어) 조건문_if,switch  (0) 2020.08.01
Comments