포인터는 주소를 저장하는 변수로 일반 변수와 마찬가지로 선언한 후에 사용한다.
방법은 변수 앞에 *를 붙여주는 것으로 완료된다.
int a; //일반 변수 선언
int *pa // 포인터 선언
pa -> a // 포인터 pa는 변수 a를 가리킨다.
포인터가 가리키는 변수를 사용할 때는 간접참조 연산자 (*)를 사용한다.
포인터에 const를 사용하는 이유
- 해당 변수의 값이 포인터를 통해 변하는 것을 방지하기 위해서.
int num = 10;
int num2 = 20;
1) const int* ptr
const int* ptr = #
ptr = 40; // 에러발생
num = 40 // 에러발생x, 값 변경
2) int *const ptr
int const ptr = #
ptr = &num2; //ptr은 num1만을 가리키는 포인터로 고정했으므로 에러
ptr = 30; // ptr이 num1을 가리키고있고, 주소에 접근해서 변경은 할 수 있다.
3) const int* const ptr
const int* const ptr = # // 값을 변경할 수 없고 참조만 가능하다.
포인터는 주소를 저장하는 메모리의 공간이다.
따라서 언제든지 다른 주소를 저장하거나 포인터끼리 대입할 수 있다.
int a,b;
int *p = &a;
p = &b;
포인터의 크기는 컴파일러에 따라 다를 수 있으므로 sizeof 연산자로 확인한다.
int *p;
sizeof(p);
포인터는 가리키는 자료형이 일치할 때만 대입한다.
int *p;
double *pd;
pd = p; // 에러발생
주소는 변수에 할당된 메모리 저장 공간의 시작 주소값 자체이고 포인터는 그 값을 저장하는 또 다른 메모리 공간이다.
특정 변수의 주소값은 변하지 않지만 포인터는 다른 주소를 대입하여 그 값을 바꿀 수 있다.
즉, 주소는 상수이고 포인터는 변수이다.
두 포인터가 같은 주소를 저장하는 일 또한 가능하다.
int a;
int *pa, *pb;
pa = pb = &a;
포인터의 크기는 컴파일러에 따라 다를 수 있으나 모든 주소와 포인터는 가리키는 자료형과 관계없이 크기가 같다.
포인터는 가리키는 변수의 형태가 같을 때만 대입해야한다.
int a = 10;
int *p = &a;
double *pb;
pb = p; // -92559532139583000000...
그러나 형변환을 사용한 포인터의 대립은 언제나 가능하다.
double a = 3.4;
double *pa = &a;
int *pd;
pd = (int *)pa; // 가능
포인터는 항상 정상적으로 할당받은 메모리 공간의 주소를 저장해서 사용해야만 한다.
포인터를 초기화하지않고 사용하는 것은 매우 위험한데, 이 경우 포인터에 간접참조 연산을 수행하면 알 수 없는 곳으로 찾아가 데이터를 바꾸게 될 수 있다.
int *p; // 초기화 되지 않은 포인터
*p = 10 // 쓰레기값으로부터 4바이트 공간에 10을 대입
포인터가 필요한 이유
모든 경우에 포인터를 사용할 이유는 없다.
포인터를 사용하려면 추가적인 변수 선언이 필요하고 각종 연산을 해야하기 때문이다.
그러나 임베디드 프로그래밍을 할 때 메모리를 직접 접근하는 경우나 동적 할당한 메모리를 사용하는 경우에는 포인터가 반드시 필요하다.
void main(void){
void swapValues(int *pa, int *pb);
int a = 10, b = 20;
swapValues(&a, &b);
printf("a : %d, b : %d \n", a, b);
return 0;
}
void swapValues(int *pa, int *pb){
int tmp;
tmp = *pa;
*pa = *pb;
*pb = tmp;
}
>> a : 20, b : 10
포인터 없이 두 변수의 값을 바꿀 수는 없을까?
int main(void){
int a = 10, b = 20;
swap();
return 0;
}
void swap(void){
int tmp;
tmp = a;
a = b;
b = tmp;
}
>> error C2065: 'a' : 선언되지 않은 식별자입니다.
error C2065: 'b' : 선언되지 않은 식별자입니다.
...
함수 안에 선언된 변수의 이름은 사용 범위가 변수가 선언된 함수 내부 블록{}에 제한되므로 main 함수 내부에 있는 변수 a,b는 다른 함수인 swap()에서 사용할 수 없다.
때문에 컴파일 단계에서 에러를 내게된다.