본문 바로가기
컴퓨터 이론/C언어 & 자료구조 & 알고리즘

03. 포인터(2)

by 컴퓨터공부용 2023. 2. 14.

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

댓글