-
04 포인터를 사용한 배열 활용
일차원 배열과 포인터
배열이름을 이용한 참조
- 배열 score
- 배열이름 score 자체가 배열 첫 원소의 주소값인 상수이다.
- 배열이름 score를 이용하여 모든 배열원소의 주소와 저장값을 참조할 수 있다.
- 배열이름 score는 배열 첫 번째 원소의 주소를 나타내는 상수로 &score[0]와 같으며 배열을 대표한다. 그러므로 간접연산자를 이용한 *score는 변수 score[0]와 같다.
- 배열이름 score가 포인터 상수로 연산식 (score+1)이 가능하다. 즉 연산식 (score+1)은 score의 다음 배열원소의 주소값을 의미한다. 즉 (score+1)은 &score[1]이다.
- (score+i) == &score[i]
- *(score+i) == score[i]
- 연산식 *(score+1)과 (*score+1)은 다르므로 주의한다. (*score+1)은 배열 첫 번째 원소에 1을 더하는 연산식이다.
int score[ ] = { 10, 20, 30 }; 주소값 참조 &score[0]
score&score[1]
score+1&score[2]
score+2배열 score 10 20 30 저장 값 참조 score[0]
*scorescore[1]
*(score+1)score[2]
*(score+2)- 배열의 주소값(배열 첫 번째 원소의 주소값) : score, &score[0]
- 배열 첫 번째 원소 저장 값 : *score, score[0]
- 배열 (i+1)번째 원소 주소값 : (score+i), &score[i]
- 배열 (i+1)번재 원소 저장 값 : *(score+i), score[i]
배열원소의 주소와 내용 값의 다양한 접근 방법
배열 초기화 문장 int score[ ] = { 10, 20, 30 }; 원소 값 10 20 30 배열원소 접근 방법 score[i] score[0] score[1] score[2] *(score+i) *score *(score+1) *(score+2) 주소값 (첫 주소 + 배열원소 크기 * i ) 100 104
(100 + 1 * 4)108
(100 + 2 * 4)주소값 접근 방법 &score[i] &score[0] &score[1] &score[2] score+i score score+1 score+2 int a[3] = { 10,20,30 }; int* p = a; # a = &a[0] # 포인터 변수 p 사용, 배열 원소 값 참조 printf("%d %d %d\n", *(p), *(p + 1), *(p + 2)); # 위 포인터 변수 p에서 배열처럼 첨자를 사용 가능 printf("%d %d %d", p[0], p[1], p[2]);
10 20 30 10 20 30
- 포인터 p에 &a[0]를 저장하면 연산식 *(p+i)로 배열원소를 참조할 수 있다.
- 특히 포인터 p로도 배열처럼 첨자를 이용해 p[i]로 배열원소를 참조할 수 있다.
- 참조연산자 *의 우선순위는 ++p의 전위 증감연산자와 같고, 괄호나 p++의 후위 증감연산자보다 낮다.
- 연산식 *p++는 *(p++)를 의미한다.
- *p++는 포인터 p가 가리키는 변수를 참조하고 p의 주소를 1 증가시킨다.
- (*p)++는 포인터 p가 가리키는 변수를 참조하고 그 값을 1 증가시키는 연산식이다.
- 연산식 *++p는 *(++p)으로 포인터 p를 1 증가시킨 후 가리키는 변수를 참조한다.
- 연산식 ++*p는 ++(*p)으로 포인터 p가 가리키는 값을 1 증가시킨 후 참조한다.
char 배열을 int 자료형으로 인식
명시적 형변환
- *pi로 수행하는 간접참조는 pi가 가리키는 주소에서부터 4byte 크기의 int 형 자료를 참조한다는 것을 의미한다.
- 변환된 포인터 변수는 지정된 주소값을 시작하여 그 변수 자료형의 크기만큼 저장공간을 참조한다.
- 동일한 메모리의 내용과 주소로부터 참조하는 값이 포인터의 자료형에 따라 달라진다.
#include <stdio.h> int main(void) { char c[4] = { 'A', '\0', '\0', '\0' }; # 문자 'A' 코드값: 65 # int *pi = &c[0]; //경고 발생 int* pi = (int*)&c[0]; printf("%d %c\n", (int)c[0], c[0]); printf("%d %c", *pi, (char)*pi); return 0; }
65 A 65 A
이차원 배열과 포인터
배열이름과 행이름으로 참조
- 이차원 배열에서 배열이름인 td는 포인터 상수 td[0]를 가리키는 포인터 상수이다.
- td[0]는 무엇일까?
- 배열의 첫 행을 대표
- 배열의 첫 번째 원소 td[0][0]의 주소값 &td[0][0]을 갖는 포인터 상수이다.
- 그러므로 배열이름인 td는 포인터의 포인터인 이중 포인터이다.
- 배열이름 td는 이차원 배열을 대표하는 이중 포인터이다.
- sizeof(td)는 배열전체의 byte 크기를 반환한다.
- 배열이름 td를 이용하여 변수 td[0][0]의 값을 20으로 수정하려면 **td = 20; 문장을 이용할 수 있다. td가 이중 포인터이므로 간접연산자 *이 2개 필요하다.
- td[i]는 (i+1)번째 행을 대표하며, (i+1)번째 행의 처음을 가리키는 포인터 상수이다. 그리고 sizeof(td[0])와 sizeof(td[1])은 각각 첫 번째 행의 바이트 크기와 두 번째 행의 바이트 크기를 반환한다.
- 마찬가지로 td[1]은 두 번째 행의 첫 원소의 주소이므로 *td[1]로 td[1][0]를 참조할 수 있다.
int td[ ][3] = {{1, 2, 3}, {4, 5, 6}}; 1 td[0][0] *(*(td + 0) + 0) *(*td + 0) 2 td[0][1] *(*(td + 0) + 1) *(*td + 1) 3 td[0][2] *(*(td + 0) + 2) *(*td + 2) 4 td[1][0] *(*(td + 1) + 0) *(*td + 3) 5 td[1][1] *(*(td + 1) + 1) *(*td + 4) 6 td[1][2] *(*(td + 1) + 2) *(*td + 5) - 연산식 (*td+n)은 배열의 (n+1)번째 원소의 주소값이다. 그러므로 역참조 연산자를 이용한 연산식 *(*td+n)은 배열의 (n+1)번째 원소 자체를 나타낸다.
- td[i]는 (i+1)번째 행의 주소이다. 그러므로 연산식(td[i]+j)는 &td[i][j]이다. 여기서 역참조 연산자를 이용한 연산식 *(td[i]+j)는 배열의 td[i][j] 원소자체를 나타낸다.
- a[i] == *(a+i)
- td[i][j] == (td[i])[j] == *(td[i]+j) == *(*(td+i)+j)
- 연산식 **td++는 연산 우선순위에 따라 **(td++)와 같으며 현재 포인터가 가리키는 원소를 참조하고 ptr을 하나 증가시켜 다음 원소를 가리키게 하는 연산식이다.
- **td === td[0][0] == *(*td+0)
포인터 배열과 배열 포인터
포인터 배열(array of pointer)
- 주소값을 저장하는 포인터를 배열 원소로 하는 배열이다.
- 포인터 변수를 선언하는 포인터 배열
int a = 5, b = 7, c = 9; int *pa[3]; pa[0] = &a; pa[1] = &b; pa[2] = &c;
포인터 배열 선언
자료형 *변수이름[배열크기]; int *p[5]; char *ptr[4]; float a, b, c; double *dary[5] = { NULL }; float *ptr[3] = {&a, &b, &c};
배열 포인터(pointer to array)
# 일차원 배열 포인터의 변수 선언 원소자료형 *변수이름; 변수이름 = 배열이름; or 원소자료형 *변수이름 = 배열이름; int a[] = {1, 2, 3, 4, 5}; int *p = a;
# 이차원 배열 포인터의 변수 선언 원소자료형 (*변수이름)[배열크기]; 변수이름 = 배열이름; or 원소자료형 (*변수이름)[배열크기] = 배열이름; int ary[][4] = {{1, 2, 3, 4, 5}, {5, 6, 7, 8, 9, 10}}; int (*ptr)[4] = ary; # 열이 4인 배열을 가리키는 포인터 int *ptr[4] = ary; # 포인터 배열
- 괄호가 없는 int *ptr[4];은 바로 전에 배운 int형 포인터 변수 4개를 선언하는 포인터 배열 선언문장이다.
- int (*ptr)[4];는 열이 4인 이차원 배열 포인터 선언문장이다.
'C' 카테고리의 다른 글
[C] 문자열와 명령행 인자② (1) 2023.05.16 [C] 문자와 문자열① (0) 2023.05.11 [C] 포인터① (1) 2023.05.04 [C] 변수 유효범위② (0) 2023.05.02 [C] 변수 유효범위① (0) 2023.04.26 - 배열 score