Q. 포인터 이해를 위한 문제
scanf()를 통한 입력을 받는 경우 저장할 변수의 주소를 이용하여 저장한다고 하였습니다. 예시) scanf("%d", &a);
그런데 문자열을 입력받아 저장하는 경우 & 연산자를 사용하지 않아도 되는데 그 이유는 무엇일까?
#include <stdio.h>
int main(){
char a[30];
scanf("%s", &a);
printf("%s\n", a);
return 0;
}
warning : format '%s' expects argument of type 'char *' but argument 2 has type 'char * [30]' |
컴파일러에 따라 다르겠지만 위와 같은 주의 메시지가 발생하게 된다.
a가 이미 주소를 나타내는 것이라, 굳이 & 연산자를 사용할 필요가 없다는 뜻이다.
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
printf("a[0]의 값 : %d\n", a[0]);
printf("a[0]의 주소 : %u\n", &a[0]);
printf("a : %u\n", a);
printf("*a : %d\n", *a);
printf("a의 주소 : %u\n", &a);
return 0;
}
a[0]의 값 : 1 a[0]의 주소 : 2422740608 a : 2422740608 *a : 1 a의 주소 : 2422740608 |
위의 결과를 보면 a[0]의 주소, a, a의 주소 모두 값이 같다는 것을 알 수 있으며,
위 값들이 가리키는 값은 모두 배열의 시작 주소라는 것을 알 수 있다.
또한 a[0]와 *a가 의미하는 것이 같다는 것도 알 수 있다.
즉, 배열의 주소를 포인터 변수에 저장하여 연산자를 활용하면 배열에 다양하게 접근할 수 있다.
배열에 접근하는 다양한 방법을 살펴보자.
#include <stdio.h>
int main()
{
int a[4][4] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
printf("a[1][1] : %d\n", a[1][1]);
printf("(*(a+1))[1] : %d\n", (*(a+1))[1]);
printf("*(a[1]+1) : %d\n", *(a[1]+1));
printf("*(*(a+1)+1) : %d\n", *(*(a+1)+1));
return 0;
}
a[1][1] : 5 (*(a+1))[1] : 5 *(a[1]+1) : 5 *(*(a+1)+1) : 5 |
위위 결과처럼 2차원 배열에 접근하는 방법이 a[1][1]을 제외하고도 다양한 방법을 통해 접근이 가능하다.
+ 연산자를 사용하여 왜 그렇게 되는지는 해당 방법들의 주소를 printf()를 이용하여 직접 출력해 보면서 주소의 변화를 관찰하면 쉽게 이해할 수 있을 것이다.
이처럼 포인터를 공부하면서 배열은 절대 빠질 수 없는 영역이다.
'컴퓨터 이론 > C언어 & 자료구조 & 알고리즘' 카테고리의 다른 글
06. 문자열 (0) | 2023.03.21 |
---|---|
05. 동적 메모리 할당(2) (0) | 2023.03.20 |
04. 동적 메모리 할당 (0) | 2023.03.20 |
02. 포인터 (0) | 2023.02.13 |
01. 구조체 (struct, typedef) (0) | 2023.02.10 |
댓글