1 byte == 8 bits
각 byte는 고유한 "address"을 가진다.
excutable program == code(statements) + data(variables)
(포인터는 여기서 data와 code 모두 가리킬 수 있음)
각 variables은 하나 이상의 byte를 차지한다.
여기서 첫번째 byte의 주소가 해당 variabe의 주소가 된다
주소는 그냥 숫자로 나오지만, 이는 일반적인 변수에 저장할 수 없다.
왜냐하면 그 주소의 범위가 type에 따라 다르기 때문이다.
즉,
1) 주소값
2) type에 따른 주소 범위
둘 다를 저장해야 되기 때문이다.
그래서 pointer variables이 등장하게 된다.
int *p; //여기서 * 은 indirection operator가 아니라, p의 type을 알려주는 것이다.
type int의 objects를 가리키는 pointer 변수 생성
(variables이 아니라 objects라고 쓴 이유는, chapter 17에서 나오겠지만, pointer variables이 꼭 변수만을 가리키진 않기 때문이다)
포인터는 선언된 type에 해당되는 object만 가리킬 수 있다. type에 대한 제한은 없다. 포인터를 가리키는 포인터도 가능하다.
&x //address of variable x
*p //access to the object that p points to
p가 아무런 메모리도 가리키지 않고 있을 때 indirection operator를 사용하는 것은 위험하다. 건들면 안될 부분을 건드릴 수 있다.
C allows the use of the assignment operator to copy pointers, "provided that they have the same type."
함수 argument는 기본적으로 그 값이 copy된다. 즉, argument를 넘겨받아도 원래 변수의 값을 수정하지 못한다.
pointer는 이런 문제를 해결해 줄 수 있다.
변수의 값을 넘겨주는 대신, 변수의 주소를 넘겨주면 된다.
scanf에서도 뒷쪽 argument에 &
를 붙였었는데, 그 이유도 이와 같은 원리라고 볼 수 있다.
그러므로 그냥 포인터 변수에 입력을 받을 거라면 scanf에서도 &
(address operator)를 붙일 필요는 없다.
보통은 argument로 포인터를 넘겨주면 그 값을 바꾸려는 거겠지만, 그렇지 않는 경우도 있다.
(값을 그냥 넘겨주면 copy되기 때문에 공간과 시간이 낭비돼서 포인터로 넘기는 경우도 있다)
그런 경우라면 const를 활용해 해당 argument를 보호할 수 있다.
void f(const int *p) //const가 앞에 오는 경우 포인터 변수가 가리키는 object를 보호
{
*p = 0; //WRONG
}
void f(int * const p) //const가 뒤에 오는 경우 포인터 변수 자체를 보호
{
int j;
p = &j; //WRONG
}
위 처럼 const가 붙는 위치에 따라 의미가 달라진다.
묶어서 보면 좀 이해됨.
const (int *p)
int * const (p)
int * f(~)
{
~
}
automatic local variable은 pointer로 반환해선 안된다.
왜냐하면 반환하고 나면 deallocate되기 때문이다.
pointer가 항상 address와 같지는 않다.
: in real mode -> segment : offset
printf에선 %p
conversion specification을 사용하면 포인터를 출력할 수 있다.