철수네 라고 알려주는 게 아니라 제대로 주소 (행복동 123번지) 라고 알려주면 찾아가기 더 쉽겠지?
포인터
특정 위치를 가리키는 주소 정보
포인터 변수
포인터(주소)를 저장하는 변수
포인터는 저장하는 데이터가 주소값이다
우린 지금까지 데이터 변수를 사용한 것(정수, 문자 등)
포인터 변수의 크기(주소의 크기)는 일반적으로 4바이트이지만 시스템에 따라 다르다
int a; 선언한 경우
임의의 메모리 공간, 현재 메모리 공간, 현재 사용하지 않은 비어있는 4바이트 공간
포인터 변수의 역할은 다른 변수를 가리키는 변수
포인터 변수의 데이터 타입은 포인팅하는 변수의 데이터 타입과 동일한 타입으로 선언
char* char형 변수의 주소 저장
int*
double*
선언 방식
데이터타입 * 포인터 변수명;
char* a;
int *b;
& : 주소 구하기 연산자
& 데이터 변수 : 변수의 주소를 의미
* 포인터 변수 : 포인터 변수가 가리키는 주소의 값
// 선언, 초기화 동시에
int a = 5;
int *pa = &a;
// 선언 후 초기화
int *pa;
pa * &a;
pa는 포인터 변수이기에 주소값을 넣을 수 있다
%p : 포인터 주소
이중포인터
포인터 변수의 주소를 저장하는 포인터 변수
주소에 주소를 저장하는 것
int x;
int *p = &x;
int **pp = &p;
포인터 오류
포인터도 변수이므로 반드시 초기화를 해야한다
포인터 변수를 초기화하지 않고 사용하면 실행 에러가 발생한다
int * p; // p는 초기화되지 않았으므로 쓰레기 값을 가진다
*p = 10; // 실행 에러가 발생한다 p가 가리키는 곳이 없으므로 에러 발생
에러가 나지 않게 하기 위해선!
널 포인터 : 포인터가 다른 변수를 가리키지 않을 때는 null(0)로 초기화한다
p를 널 포인터로 초기화한다 p는 아직 다른 변수를 가리키지 않는다
int *p = null;
포인터를 안전하게 사용하려면 우선 포인터가 널 포인터인지를 검사
if(p! = null)
*p = 10; // p가 널 포인터가 아닌지 확인 후에 사용하는 게 좋은 습관이다
포인터 변수의 데이터형이 반드시 포인터 변수가 가리키는 변수의 데이터형과 일치해야 한다
short a;
int *p = &a;
*p = 10;
*pt는 pt가 가리키는 주소의 내용을 의미한다
포인터 변수를 초기화하는 문장으로 옳은 것은?
포인터 변수에 변수의 주소를 저장해야 한다
char a; char *p = &a;
배열명
배열의 시작 주소를 의미하는 상수
배열의 시작 주소를 구할 때는 & 없이 배열명만 사용
배열의 시작 주소는 첫번째 원소의 주소와 같다
arr = &arr[0]
배열명을 포인터처럼 사용하는 게 가능하다
인덱스를 사용하는 대신 배열의 시작 주소로 포인터 연산을 하면 배열의 특정 원소에 접근이 가능하다
*(arr + i)는 arr[i]를 의미
배열의 시작 주소에서 데이터 타입 i개 크기만큼 증가된 주소에 있는 값
*(arr+0) = arr[0]
배열의 i번째 원소의 주소 / 배열 시작 주소에서 i개의 원소(인덱스)만큼 떨어진 주소
&arr[i] = arr + i
배열의 i번째 원소 / 배열 시작 주소에서 i개의 원소만큼 떨어진 주소에 있는 값
arr[i] = *(arr + i)
배열의 시작 주소로 초기화된 포인터를 이용해서 배열의 모든 원소에 접근 가능
포인터 변수를 배열 이름인 것처럼 사용 가능
배열명은 그 배열의 시작 주소를 의미한다
a에 &가 안붙지? a 자체가 주소이다
그렇기에 이 배열의 시작 주소 a가 p에 들어간다
int a[4];
int *p = a;
*(p + i) == p[i];
p + i == &p[i];
배열과 포인터의 차이점
배열이 메모리에 할당되고 나면 배열의 시작 주소 변경 불가 - 상수
포인터 변수는 값을 변경할 수 있으므로 포인터 변수에 보관된 주소는 변경이 가능하다- 변수
포인터에 대한 증감 연산도 포인터형에 의해 연산의 결과가 결정된다
우선순위 : p++ > ++p = *
*p++ = *(p++)
++*p = ++(*p)
포인터 배열 : 주소를 저장하는 배열
형식 데이터타입 *포인터 변수명[크기];
int a = 10, b = 20, c = 30, d = 40, e = 50;
int *arr[5] = {&a, &b, &c, &d, &e};
*arr[i]
int i;
int a = 1, b = 2, c = 3, d = 4, e = 5;
int *arr[5] = {&a, &b, &c, &d, &e};
for(i = 0; i < 5; i++) {
printf("%d", *arr[i]);
}
뭔말인지... 너무 헷갈려ㅜㅜ
str[3][10]
str = str[0] = &str[0][0]
str : 이중포인터처럼 사용된다고도 말할 수 있다
**str = *str[0] = str[0][0]
문자열 상수를 문자형 포인터 변수에 저장
char *p = "korea";
p라는 변수는 포인터 변수. 이렇게 적으면 p라는 변수에 들어간다고 생각할 수 있지만 포인터 변수는 4바이트짜리 주소를 보관하는 공간이다.
근데 이건 문자 데이터이다.
그래서 이 korea 문자를 메모리 공간에 보관하고 이것을 p 주소에 보관하는 것이다
p는 주소이기에 p[2] = 'r'이 안된다. 배열이 아니기에! 주소에 담는 건 안되니까
char p[] = "korea";
p[2] = 'r';
이것은 가능하다
값 대입은 안되지만 주소에 값 출력은 가능하다