12 - Array And Pointer 1
<학습하기>
배열(Array)
같은 성질을 가진 여러개의 데이터를 묶어 하나로 관리할 수 있도록 하는 데이터 구조.
[일주일간의 판매액 데이터] 역시 '하루하루의 판매액' 이라는 같은 성질을 갖고 있으므로
배열로 관리할 수 있다.
만약 [나이], [생년], [C언어 점수] 와 같이 전혀 상관없는 데이터들이라면
배열로 묶지 않고 따로 관리하는 것이 효율적이다.
배열 만들기 (int배열로 설명)
1.기본 배열 생성.
데이터타입 배열이름 [배열크기]
int array [10];
정수형 데이터 10개를 저장할 수 있는 배열을 생성해서 array라 이름 짓는다.
이때는 각 변수에 어떤 값이 들어가 있는지 알 수 없음.
2. 생성과 함께 초기화
int array [10]; = {1,2,3,4,5,6,7,8,9,10};
정수형 데이터 10개를 저장할 수 있는 배열을 만듦과 동시에
1~10까지의 값으로 초기화.
int array [ ] = {1,2,3,4,5,6,7,8,9,10};
크기가 생략되어 있을 경우, 초기화 값의 갯수를 세어 그 크기만큼의 배열을 만듦.
int array [10] = {1,2,3};
초기화 값이 배열 크기보다 작을 경우 모자라는 값들은 0으로 채워짐.
int array [10] = {1,2,3,4,5,6,7,8,9,10,11};
배열 크기에 비해 초기화값이 많으면 컴파일시 에러가 난다.
배열 자체는 여러개의 변수들의 묶음이다.
배열에서 특정한 변수의 값을 가져오거나, 특정한 변수에 값을 대입하는 작업이 필요하다.
이런 작업을 할 수 있도록 하는 것을 첨자(subscript)라 한다.
형식
배열이름 [첨자]
[첨자]의 식을 계산한 후, 이 [배열이름]에서 해당위치의 변수를 가져온다.
단, 첨자는 "??번째 변수"를 의미하므로 정수만 사용가능하며, zero base이다.
즉, int arr [10];으로 만들어진 배열이라면 arr[0]~arr[9]까지 사용 가능하다.
첨자는 수식을 사용할 수 있으므로 반복문과 결합할 때 높은 효율을 보인다.
주의
C프로그램은 첨자 입력을 전혀 검증하지 않는다.
첨자가 배열의 범위를 넘어가거나 -값이 들어가도
C프로그램은 아무 생각 없이 실행해 버리므로 에러의 원인이 될 수 있다.
배열과 포인터의 관계
int sale[7]; 로 만들어진 배열의 각 변수들을 출력해 보면,
각변수들의 주소가 4바이트 (int변수의 크기) 만큼씩 떨어져 있음을 알 수 있다.
즉, 정수형 배열은 정수형 변수들이 차곡차곡 붙어있는 모습임을 알 수 있다.
또한 변수명인 sale을 출력해 본다면,
sale이 가지는 값은 sale[0]의 주소와 동일하며,
결국 sale이라는 배열이 시작되는 위치임을 알 수 있다.
sale 자체가 [sale이라는 배열이 시작되는 주소]를 의미하므로
sale 역시 일종의 [포인터]라고 할 수 있다.
단, 일반 포인터와는 달리 sale은 다른 변수를 대입할 수 없다.
즉 [배열은 값을 바꿀 수 없는 포인터]이며,
[포인터는 값을 바꿀 수 있는 배열] 이라고 할 수 있다.
포인터의 연산
포인터 + 정수
포인터 - 정수
포인터에 정수를 더하거나 뺴면 해당 포인터 타입의 크기만큼의 단위로 증가하거나 감소한다.
int *intPnt;
intPnt += 5 >> 실제로는 5*sizeof(int)만큼 증가
intPnt -= 3 >> 실제로는 3*sizeof(int)만큼 감소
포인터의 캐스팅
<실습하기>
#include <stdio.h>
//어느 상점에서 3일간의 판매액을 입력하여 하루 평균 판매량을 구하여라.
main()
{
/*
int sale1;
int sale2;
int sale3;
double avg;
printf("3일간의 판매액을 입력하세요.");
scanf("%d %d %d", &sale1, &sale2, &sale3);
avg = (sale1 + sale2 + sale3)/3.0;
printf("평균판매액 : %f\n", avg);
*/
//어느 상점에서 일주일간의 판매액을 입력하여 하루 평균 판매량을 구하여라.
int sale[7] = {352, 534, 257, 634, 524, 342, 473}; //초기화값 갯수만큼 7개의 배열 생성
//데이터 출력
/*
printf("1째날 매출액 : %d\n", sale[0]);
printf("2째날 매출액 : %d\n", sale[1]);
printf("3째날 매출액 : %d\n", sale[2]);
printf("4째날 매출액 : %d\n", sale[3]);
printf("5째날 매출액 : %d\n", sale[4]);
:
:
이렇게 쓰기보다는 반복문을 쓰는게 좋다.
*/
int day;
int total;
double avg;
for(day = 0; day <7; ++day) //여기서 day<31로 하면 이상값 불러옴 ㅎ
printf("%d째날 매출액 : %d\n", day + 1, sale[day]);
/*
total = 0;
total += sale[0];
total += sale[1];
삽질하지말고 반복문 쓰기
*/
total = 0;
for(day = 0; day <7; ++day)
total += sale[day];
avg = total / 7.0;
printf("평균 매출액 : %f\n", avg);
puts("");
puts("배열과 포인터");
{
int *salePnt = NULL;
printf("sale : %d\n", sale); // sales는 배열이니까 이때는 주소가 출력됨.
for (day = 0; day < 7; ++day)
printf("sale[%d] : %d\n", day, &sale[day]);
puts("");
puts("salePnt를 사용한 출력");
salePnt = sale;
for(day=0; day<7; ++day)
printf("%d일째 매출액 : %d\n", day + 1, salePnt[day]); // sale 대신 salePnt 사용.
//sale 대신에 salePnt를 사용했음에도 정확한 출력이 나옴.
}
puts("");
puts("포인터의 연산");
{
int *salePnt = sale;
/*
printf("salePnt : %d\n", salePnt);
printf("salePnt +1 : %d\n", salePnt+1);
printf("salePnt +2 : %d\n", salePnt+2);
printf("salePnt +3 : %d\n", salePnt+3);
printf("salePnt +4 : %d\n", salePnt+4);
*/
for(day =0; day < 7; ++day)
{
printf("%d째날 매상 : %d\n", day+1, *salePnt); // salePnt가 가리키고 있는 위치의 데이터를 가져옴.
++salePnt;
}
}
}
배열(Array)
같은 성질을 가진 여러개의 데이터를 묶어 하나로 관리할 수 있도록 하는 데이터 구조.
[일주일간의 판매액 데이터] 역시 '하루하루의 판매액' 이라는 같은 성질을 갖고 있으므로
배열로 관리할 수 있다.
만약 [나이], [생년], [C언어 점수] 와 같이 전혀 상관없는 데이터들이라면
배열로 묶지 않고 따로 관리하는 것이 효율적이다.
배열 만들기 (int배열로 설명)
1.기본 배열 생성.
데이터타입 배열이름 [배열크기]
int array [10];
정수형 데이터 10개를 저장할 수 있는 배열을 생성해서 array라 이름 짓는다.
이때는 각 변수에 어떤 값이 들어가 있는지 알 수 없음.
2. 생성과 함께 초기화
int array [10]; = {1,2,3,4,5,6,7,8,9,10};
정수형 데이터 10개를 저장할 수 있는 배열을 만듦과 동시에
1~10까지의 값으로 초기화.
int array [ ] = {1,2,3,4,5,6,7,8,9,10};
크기가 생략되어 있을 경우, 초기화 값의 갯수를 세어 그 크기만큼의 배열을 만듦.
int array [10] = {1,2,3};
초기화 값이 배열 크기보다 작을 경우 모자라는 값들은 0으로 채워짐.
int array [10] = {1,2,3,4,5,6,7,8,9,10,11};
배열 크기에 비해 초기화값이 많으면 컴파일시 에러가 난다.
배열 자체는 여러개의 변수들의 묶음이다.
배열에서 특정한 변수의 값을 가져오거나, 특정한 변수에 값을 대입하는 작업이 필요하다.
이런 작업을 할 수 있도록 하는 것을 첨자(subscript)라 한다.
형식
배열이름 [첨자]
[첨자]의 식을 계산한 후, 이 [배열이름]에서 해당위치의 변수를 가져온다.
단, 첨자는 "??번째 변수"를 의미하므로 정수만 사용가능하며, zero base이다.
즉, int arr [10];으로 만들어진 배열이라면 arr[0]~arr[9]까지 사용 가능하다.
첨자는 수식을 사용할 수 있으므로 반복문과 결합할 때 높은 효율을 보인다.
주의
C프로그램은 첨자 입력을 전혀 검증하지 않는다.
첨자가 배열의 범위를 넘어가거나 -값이 들어가도
C프로그램은 아무 생각 없이 실행해 버리므로 에러의 원인이 될 수 있다.
배열과 포인터의 관계
int sale[7]; 로 만들어진 배열의 각 변수들을 출력해 보면,
각변수들의 주소가 4바이트 (int변수의 크기) 만큼씩 떨어져 있음을 알 수 있다.
즉, 정수형 배열은 정수형 변수들이 차곡차곡 붙어있는 모습임을 알 수 있다.
또한 변수명인 sale을 출력해 본다면,
sale이 가지는 값은 sale[0]의 주소와 동일하며,
결국 sale이라는 배열이 시작되는 위치임을 알 수 있다.
sale 자체가 [sale이라는 배열이 시작되는 주소]를 의미하므로
sale 역시 일종의 [포인터]라고 할 수 있다.
단, 일반 포인터와는 달리 sale은 다른 변수를 대입할 수 없다.
즉 [배열은 값을 바꿀 수 없는 포인터]이며,
[포인터는 값을 바꿀 수 있는 배열] 이라고 할 수 있다.
포인터의 연산
포인터 + 정수
포인터 - 정수
포인터에 정수를 더하거나 뺴면 해당 포인터 타입의 크기만큼의 단위로 증가하거나 감소한다.
int *intPnt;
intPnt += 5 >> 실제로는 5*sizeof(int)만큼 증가
intPnt -= 3 >> 실제로는 3*sizeof(int)만큼 감소
포인터의 캐스팅
포인터는 캐스팅을 통해 다른 타입의 포인터로 대입이 가능하다.
특히 void의 포인터 (void*)는 아무 캐스팅 없이 다른 포인터의 대입이 가능하다.
void *commonPnt;
commonPnt =&intVar;
commonPnt =&dblVar;
inrPnt = (int*)commonPnt;
intPnt = 10;
포인터 캐스팅 잘못하면 엄청난 버그 ㅜㅠ
포인터간의 캐스팅은 나중에 찾기 힘든 오류가 생길 가능성이 매우 크므로 가능하면 사용하지 않는 것이 좋다.
<실습하기>
#include <stdio.h>
//어느 상점에서 3일간의 판매액을 입력하여 하루 평균 판매량을 구하여라.
main()
{
/*
int sale1;
int sale2;
int sale3;
double avg;
printf("3일간의 판매액을 입력하세요.");
scanf("%d %d %d", &sale1, &sale2, &sale3);
avg = (sale1 + sale2 + sale3)/3.0;
printf("평균판매액 : %f\n", avg);
*/
//어느 상점에서 일주일간의 판매액을 입력하여 하루 평균 판매량을 구하여라.
int sale[7] = {352, 534, 257, 634, 524, 342, 473}; //초기화값 갯수만큼 7개의 배열 생성
//데이터 출력
/*
printf("1째날 매출액 : %d\n", sale[0]);
printf("2째날 매출액 : %d\n", sale[1]);
printf("3째날 매출액 : %d\n", sale[2]);
printf("4째날 매출액 : %d\n", sale[3]);
printf("5째날 매출액 : %d\n", sale[4]);
:
:
이렇게 쓰기보다는 반복문을 쓰는게 좋다.
*/
int day;
int total;
double avg;
for(day = 0; day <7; ++day) //여기서 day<31로 하면 이상값 불러옴 ㅎ
printf("%d째날 매출액 : %d\n", day + 1, sale[day]);
/*
total = 0;
total += sale[0];
total += sale[1];
삽질하지말고 반복문 쓰기
*/
total = 0;
for(day = 0; day <7; ++day)
total += sale[day];
avg = total / 7.0;
printf("평균 매출액 : %f\n", avg);
puts("");
puts("배열과 포인터");
{
int *salePnt = NULL;
printf("sale : %d\n", sale); // sales는 배열이니까 이때는 주소가 출력됨.
for (day = 0; day < 7; ++day)
printf("sale[%d] : %d\n", day, &sale[day]);
puts("");
puts("salePnt를 사용한 출력");
salePnt = sale;
for(day=0; day<7; ++day)
printf("%d일째 매출액 : %d\n", day + 1, salePnt[day]); // sale 대신 salePnt 사용.
//sale 대신에 salePnt를 사용했음에도 정확한 출력이 나옴.
}
puts("");
puts("포인터의 연산");
{
int *salePnt = sale;
/*
printf("salePnt : %d\n", salePnt);
printf("salePnt +1 : %d\n", salePnt+1);
printf("salePnt +2 : %d\n", salePnt+2);
printf("salePnt +3 : %d\n", salePnt+3);
printf("salePnt +4 : %d\n", salePnt+4);
*/
for(day =0; day < 7; ++day)
{
printf("%d째날 매상 : %d\n", day+1, *salePnt); // salePnt가 가리키고 있는 위치의 데이터를 가져옴.
++salePnt;
}
}
}
댓글
댓글 쓰기