[정보처리기사] C언어 - 배열과 포인터(배열에도 주소값이 있다)
포인터 변수는 주소를 가진다
배열도 주소를 가지는데
예를 들어
int a[5]로 배열을 선언하게 되면,
a라는 변수가 메모리 어딘가에 만들어지고 메모리 상에 5개의 공간이 만들어지는데,
배열 a가 가지는 주소는 배열의 [0] 즉, 첫 번째 주소와 같은 주소를 가진다.
다른 말로 a의 주소는 100이다
표로 나타내 보면
a | 배열 | 메모리 주소 | 메모리 주소의 값 |
100 | [0] | 100 | |
[1] | 101 | ||
[2] | 102 | ||
[3] | 103 | ||
[4] | 104 |
ex.
#include<stdio.h>
int main(void){
int i;
int a[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int *ptr = a+3
for(i=0; i<5; ++i) {
printf("%d", *(ptr+i)-3);
}
}
해설
미리 알아야 하는 것
1.
int *ptr = a + 3인데, a는 배열이고, 주소를 배열의 첫 번째 주소를 공유하므로
ptr 주소는 100+3 = 103이다. (103번지를 참조함)
*ptr은 주소의 값이므로 103번지에 있는 값인 40
2. for문의 진행 구조
for (초기식; 조건식; 증감식)
{
수행하는 작업
}
for문의 기본 수행 순서
0. 초기식 확인
1. 조건식 확인한다 -> (조건을 만족하면)
2. 수행하는 작업을 한 후
3. 증감식을 수행한다.
다시 1번으로 돌아가서 조건이 만족할 때까지 수행한다.
조건이 거짓이면 for문을 빠져나온다.
배열은 배열의 첫 번째 주소를 가진다.
즉 a의 배열의 주소는 100번지라고 가정.
위의 배열을 표로 표현해보면 아래와 같다
임의의 주소 | 100번지 | 101번지 | 102번지 | 103번지 | 104번지 | 105번지 | 106번지 | 107번지 | 108번지 | 109번지 | |
a | 배열주소 | a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | a[8] | a[9] |
100번지 | 주소의 값 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 |
이제 for문을 진행시키면서 포인터가 어디를 가르키는지 천천히 봐보자.
i (i<5) | ptr = (a+3) | *ptr = 포인터 변수의 주소의 값 | *(ptr+i)-3 | i++ | |
초기값 | 0 | 103 | 40(103번지의 주소의 값) | ||
i=0 | *(103+0)-3 = *(103): 103번지의 값 40에서 -3 = 37 | 1 | |||
i=1 | 1 | 103 | 40 | *(103+1)-3 = *(104): 104번지의 값 50에서 -3 = 47 | 2 |
i=2 | 2 | 103 | 40 | *(103+2)-3 = *(105): 105번지의 값 60에서 -3 = 57 | 3 |
i=3 | 3 | 103 | 40 | *(103+3)-3 = *(106): 106번지의 값 70에서 -3 = 67 | 4 |
i=4 | 4 | 103 | 40 | *(103+4)-3 = *(107): 107번지의 값 80에서 -3 = 77 | 5 |
i=5 | false |
즉
37,47,57,67,77 값이 출력된다.
배열과 포인터의 관계
int a[5]; 배열을 생성하게 되면
배열 a | 임의의 번지 | 100번지 | 101번지 | 102번지 | 103번지 | 104번지 | |
100번지 | 배열 | a[0] | a[1] | a[2] | a[3] | a[4] | |
번지수의 값 |
위와 같은 표를 얻고
배열 a의 번지는 배열의 첫 번째 번지수를 공유하므로 a = 100번지이다.
int *b = a;
배열 a가 100번지 이므로 포인터 변수 b에 100번지를 할당한다
a[2] = 10;
배열 a | 임의의 번지 | 100번지 | 101번지 | 102번지 | 103번지 | 104번지 | |
100번지 | 배열 | a[0] | a[1] | a[2] | a[3] | a[4] | |
번지수의 값 | 10 |
위에 포인터 변수 b를 선언했기 때문에
b[2] = 20; -> 포인터 변수 2번째 공간을 의미한다
배열 a | 임의의 번지 | 100번지 | 101번지 | 102번지 | 103번지 | 104번지 | |
100번지 | 배열 | a[0] | a[1] | a[2] | a[3] | a[4] | |
번지수의 값 | 20 |
이렇게 표현할 수 있다.
ex.
#include<stdio.h>
int main(void) {
int a[] = {1, 2, 4, 8};
int *p = a;
p[1] = 3;
a[1] = 4;
p[2] = 5;
printf("%d %d₩n", a[1] + p[1], a[2] + p[2]);
return 0
}
해설
a | 임의의 번지수 | 100 | 101 | 102 | 103 |
100 | 배열 | a[0] | a[1] | a[2] | a[3] |
번지수의 값 | 1 | 2 | 4 | 8 |
p(int *p = a) | a | 임의의 번지수 | 100 | 101 | 102 | 103 |
100 | 100 | 배열 | a[0] | a[1] | a[2] | a[3] |
기존 번지수의 값 | 1 | 2 | 4 | 8 | ||
할당된 번지수의 값 | 3(p[1] = 3) | |||||
4(a[1] = 4) | 5 (p[2] = 5) | |||||
최종 배열 | 1 | 4 | 5 | 8 |
이 상태에서 a[1] + p[1], a[2] + p[2]를 출력하면
4+4, 5+5
8과 10이 출력된다.
ex.
#include<stdio.h>
int main(void){
int a[4] = {10, 20, 30};
int *p = a;
p++;
*p++ = 100;
*++p = 200;
printf("a[0] = %d, a[1] = %d, a[2] = %d₩n, a[0], a[1])
}
해설
배열a | 임의의 주소값 | 100 | 101 | 102 | 103 |
100 | 배열 | a[0] | a[1] | a[2] | a[3] |
주소의 값 | 10 | 20 | 30 |
int *p = a
p | 배열a | 임의의 주소값 | 100 | 101 | 102 | 103 | |
100 | 100 | 배열 | a[0] | a[1] | a[2] | a[3] | |
주소의 값 | 10 | 20 | 30 |
p++;
*p++ = 100; ->p의 주소의 값을 할당 하고 ++
*++p = 200; ->먼저 ++하고 p의 주소의 값 할당
p | p++ | *p++ =100 | *++p = 200 |
100 | 101 | p의 값을 할당한 후에 ++ 101번지의 값 = 20에 100 할당 p++ = 102 |
p먼저 ++ -> 102->103번지의 값 = 30에 200할당 |
p | 배열a | 임의의 주소값 | 100 | 101 | 102 | 103 |
100 | 100 | 배열 | a[0] | a[1] | a[2] | a[3] |
최종 주소의 값 | 10 | 100 | 30 | 200 |
printf("a[0] = %d, a[1] = %d, a[2] = %d₩n, a[0], a[1],a[2])
답
a[0] = 10, a[1] = 100, a[2] = 30
ex.
#include<stdio.h>
void main() {
int num[4] = {1,2,3,4};
int *pt = num;
pt++;
*pt++ = 5;
*pt++ = 10;
pt--;
*pt+++=20;
printf("%d %d %d %d", num[0], num[1], num[2], num[3]);
}
해설
배열의 주소가 배열 첫 번째 값의 주소를 참조한다.
num = 100, pt도 100
pt | num | 임의의 주소 | 100번지 | 101번지 | 102번지 | 103번지 |
100 | 100 | 배열 | num[0] | num[1] | num[2] | num[3] |
주소의 값 | 1 | 2 | 3 | 4 |
pt++; -> pt값을 할당하고 ++ // 100-> 101
*pt++ = 5; -> pt의 주소의 값에 5 할당하고 ++ // 101번지 값에 5할당하고 102
*pt++ = 10; -> pt의 주소의 값에 10할당하고 ++ // 102번지 값에 10할당하고 103
pt--; -> pt -> pt값 -- // 103->102
*pt+++=20; -> 102번지의 값에 *pt = *pt + 20할당 이후에 pt ++ // pt의 주소의 값에, 주소의 값 + 20을 할당(10+20)하고 103
pt | pt++ | pt-- | num | 임의의 주소 | 100번지 | 101번지 | 102번지 | 103번지 |
100 | 100 | 배열 | num[0] | num[1] | num[2] | num[3] | ||
주소의 값 | 1 | 2 | 3 | 4 | ||||
101 | 5 | |||||||
102 | 10 | |||||||
103 | ||||||||
102 | 30 | |||||||
103 | ||||||||
최종 | 103 | 100 | 1 | 5 | 30 | 4 |
printf("%d %d %d %d", num[0], num[1], num[2], num[3])
1,5,30,4 출력