jam 블로그

[C] 13. 포인터와 배열 본문

개발 및 관련 자료/C

[C] 13. 포인터와 배열

kid1412 2013. 5. 12. 19:34
728x90

I. 포인터와 배열의 관계

  • 배열의 이름은 무엇을 의미하는가?

    • 배열의 이름은 포인터다. 단 그 값을 바꿀수 없는 상수라는 점이 일반적인 포인터와의 유일한 차이점
#include <stdio.h>
int main()
{
    int a[5] = {0,1,2,3,4};
    printf("%d, %d\n",a[0],a[1]);
    printf("%d, %d\n",&a[0],&a[1]); 
    printf("배열이름 : %d\n",a);
    return 0;
}
  • 위의 소스를 보면 처음의 printf는 a[0],a[1]의 값을 찍는거고 , 두번째 printf는 각각의 주소값을 세번째 printf는 배열이름에 대한 주소를 찍는다.

    • 결과를 보면 &a[0]와 a는 같다.
 비교조건/비교대상 포인터  배열이름 
 이름이 존재하는가? Yes Yes 
 이름은 무엇을 나타내는가?  메모리의 주소 메모리의 주소 
 변수인가? Yes  No 
 상수인가?  No Yes 

  • 포인터와 배열이름의 차이점은 배열이름이 상수이다보니 상관 없다. 따라서 상수 포인터라 한다.
#include <stdio.h>
int main()
{
    int a[5] = {0,1,2,3,4};
    int b = 10;
    a = &b;
}
  •  마지막 줄 a는 상수 이므로 변수인 &b를 넣을수 없다.

 

  •  1차원 배열이름의 포인터 타입

    • int a[10] 이라면 int*형이다.
  • 포인터를 배열의 이름처럼 사용할 수 있다.
#include <stdio.h>
int main()
{
    int arr[3] = {0,1,2};
    int *ptr;
    ptr = arr;
    printf("%d,%d,%d\n",ptr[0],ptr[1],ptr[2]);
    return 0;
}
  •   위 소스처럼 arr를 포인터 처럼 써서 넘겨줄 수 있다.

II. 포인터 연산

  • 포인터는 제한된 형태의 연산이 가능하다
#include <stdio.h>
int main()
{
    int *ptr = 0;
    char *ptr1 = 0;
    double *ptr2 = 0;
    printf("%d,%d,%d\n",ptr++,ptr1++,ptr2++);
    printf("%d,%d,%d\n",ptr,ptr1,ptr2);
    return 0;
}
  • 먼저 ptr,ptr1,ptr2를 찍고 각각 하나씩 증가한다음  각 타입만큼 증가 시켜서 그다음번에 4,1,8을 찍는다.

    • 포인터 연산에 따른 실질적인 값의 변화는 포인터 타입에 따라 다르다.
#include <stdio.h>
int main()
{
    int arr[5] = {1,2,3,4,5};
    int *parr = arr;
    printf("%d\n",*parr);
    printf("%d\n",*(++parr));
    printf("%d\n",*(++parr));
    printf("%d\n",*(parr+1));
    printf("%d\n",*(parr+2));
    return 0;
}
  • 위의 소스를 보면 *(parr+1) 같은것이 보인다.

    • 잘 생각해보면 parr은 배열의 이름(즉 배열의 첫번째 주소값)이 들어가있다. 거기에 +n 을 하면 더한만큼의 배열을 가리킨다.
  •  중요한 결론! arr[i] = *(arr+i)

III. 문자열 상수를 가리키는 포인터

  • 문자열 표현 방식의 이해

    •  변수로 표현하는 방법 : char str1[5] = "ABCD";
    • 상수로 표현하는 방법 : char *str2 = "abcd;
#include <stdio.h>
int main()
{
    char str1[5] = "abcd";
    char *str2 = "ABCD";
    printf("%s\n",str1);
    printf("%s\n",str2);
    str1[0] = 'x';
    str2[0] = 'x';
    printf("%s\n",str1);
    printf("%s\n",str2);
    return 0;
}
  •  위의 소스는 컴파일은 잘된다 하지만 실행시 오류가 난다 어디서 날까?

    •  str2[0] = 'x'; 이것이 잘못 된 것이다. 왜냐하면 str2는 문자열 상수를 변경하려고 하기 때문이다.
  • 문자열 상수에 대한 조금 더 깊은 이해

    • 문자열 상수는 메모리 공간에 할당되면 주소를 반환한다.
  • 똑같은 문자열을 선언하면 한번만 메모리 공간에 할당된다.
#include <stdio.h>
int main()
{
    char *str1 = "ABCD";
    char *str2 = "ABCD";
    printf("%d,%d\n",str1,str2);
    return 0;
}
  • 좋은 컴파일러는 똑같은 코드라 할지라도 메모리를 효율적으로 사용하기위해서 최적화를 한다.

IV. 배열 요소로 포인터를 지니는 포인터 배열

  • 포인터 배열의 이해
#include <stdio.h>
int main()
{
    int a = 10, b= 20, c = 30;
    int* arr[3]={&a,&b,&c};
    printf("%d\n\",*arr[0]);
    printf("%d\n\",*arr[1]);
    printf("%d\n\",*arr[2]);
    return 0;
}
Comments