포인터란?
- 메모리에는 바이트단위로 그 위치를 식별할 수 있는 물리적인 주소값이 있다.
-메모리의 용량이 64kb라면 주소값은 0번지부터 65535번지까지 존재한다.64kbyte = 64 X 1024 = 65535 (1k = 2의 10승 = 1024)
- 변수를 선언하면 그 자료형의 크기만큼 메모리에 연속된 바이트의 기억공간이 할당되는데 그 첫번째 바이트의 주소값이 포인터이다.
- 이 포인터를 사용하여 4바이트의 기억공간에 값을 저장하거나 저장된 값을 꺼내어 쓸 수 있다.
주소연산자 -> 주소 읽기 연산자
- 특정 변수의 포인터를 구하기 위해서는 주소연산자(&)를 사용한다.
& gayeong -> 포인터를 구해준다. 주소연산자 / 변수명
- 포인터를 구하여 출력
char ch; int in; double db; printf("ch의 포인터 : %u\n", &ch); printf("in의 포인터 : %u\n", &in); printf("db의 포인터 : %u\n", &db); -> ch의 포인터 : 1245052 //char형 변수의 주소값 in의 포인터 : 1245048 //int형 변수의 시작 주소값 db의 포인터 : 1245040 //double형 변수의 시작 주소값
포인터는 특정 자료형을 가리킨다.
- 포인터에는 자신이 어떤 자료형으로부터 만들어졌는지에 대한 정보를 가지고 있다.
- 포인터가 특정 자료형에 대한 정보를 가지고 있다는 것을 간단히 표현할 때 "가리킨다"고 하고 화살표를 사용하여 그림을 그린다.
int형 변수 gayeong을 가리키는 포인터 &gayeong -> 변수 gayeong //4바이트의 기억공간 전체를 가리킨다.
참조연산자 -> 데이터 쓰기 / 읽기 연산자
- 포인터를 통해서 기억공간을 사용하기 위해서는 참조연산자(*)를 사용한다.
포인터에 참조연산자 붙이면 * & gayeong -> 포인터가 가리키는 기억공간 사용 -> 변수처럼 사용 참조연산자 / 포인터(& gayeong)
char ch; int in; double db; *&ch = 'P'; //포인터 &ch가 가리키는 기억공간에 'P'를 저장 *&in = 100; //포인터 &in가 가리키는 기억공간에 100를 저장 *&db = 3.14; //포인터 &db가 가리키는 기억공간에 3.14를 저장 printf("변수 ch에 저장된 문자 : %c\n", ch); printf("변수 in에 저장된 문자 : %d\n", in); printf("변수 db에 저장된 문자 : %lf\n", db); -> 변수 ch에 저장된 문자 : P 변수 in에 저장된 값 : 100 변수 db에 저장된 값 : 3.140000
참조연산자
- "참조"는
- 기억공간을 사용 -> 데이터 쓰기
- 기억공간에 저장된 값도 사용 -> 데이터 읽기
int a=100, b=0; b = *&a; //포인터 &a가 가리키는 기억공간의 값을 b에 대입 printf("b의 값 : %d\n", b);
- 기억공간을 사용하는 것과 값을 사용하는 것은 대입연산자의 어디에 위치하느냐에 따라 결정된다. ★ 포인터 -> 실체?
int a=10, b=20; *&a = *&b; //변수 b에 저장된 값을 변수 a의 기억공간에 저장 printf("a의 값 : %d\n", a); //a의 값은 20이 출력 -> 기억공간을 사용(왼쪽) *&a = *&b; 기억공간의 값을 사용(오른쪽) => a=b; 오른쪽의 값을 왼쪽의 기억공간에 저장한다.
포인터변수
- 포인터의 값 자체는 정수 값이지만 가리키는 자료형에 대한 정보를 가지고 있으므로 정수형 변수에 저장할 수 없다.
★ 포인터 = 주소 + 자료형 정보 ★
int a; //포인터를 구할 변수 int ap; //포인터를 저장할 변수 ap = &a; //a의 포인터를 구해서 ap에 저장
- 직관적으로는 충분히 가능할 듯 하지만 컴파일 에러가 발행한다.
- 포인터는 포인터가 가진 정보를 그대로 보존할 수 있도록 "포인터변수에 저장해야 한다."
- 포인터변수는 변수명 앞에 '*'을 붙이고 가리키는 자료형을 앞에 적어준다.
-int형 변수의 포인터를 저장하는 포인터변수의 선언int *ap; 가리키는 자료형을 앞에 붙임/변수명 앞에 *을 붙여 포인터변수임을 표시 -> 이름은 ap고 포인터변수이다. int형 변수의 시작주소값만을 저장. 그래서 int형 변수를 가리킨다고 함.
포인터변수가 포인터를 저장하면 포인터와 마차낙지로 기억공간을 가리킨다.
int a; int *ap; ap = &a;
포인터변수를 사용한 참조
- 포인터를 저장한 포인터변수도 참조연산자로 그것이 가리키는 기억공간 또는 그 기억공간의 값을 사용할 수 있다.
int a; //int형 변수의 선언 int *ap = &a; //포인터변수의 선언과 동시에 초기화, ap는 변수a를 가리킨다. *ap = 10; //포인터변수가 가리키는 기억공간에 10 저장 //ap에 a의 주소값을 저장 //주소값에 별표(참조연산자)를 붙이면 그 주소의 실체를 의미! //a주소값의 실체는 a와 같다. -> a=10
- 포인터변수도 하나의 변수이므로 주소연산자로 메모리에서의 위치를 구할 수 있다.
int a; //int형 변수의 선언 int *ap = &a; //포인터변수의 선언과 동시에 초기화, ap는 변수a를 가리킨다. printf("ap에 저장된 값 : %u\n", ap); //변수 a의 시작주소값 출력 printf("ap자체의 주소값 : %u\n", &ap); //vhdlsxj //포인터변수 ap의 시작주소값 출력
포인터 정리
int a = 10; //int형 변수 선언, 정수값 10으로 초기화
int *ap = &a; //int포인터변수 선언, a의 시작주소값으로 초기화
4.48 <시작주소값> 2.52
3.주소값 52 ----> 1.정수값 10
포인터변수 ap int형 변수 a
printf("%d", a); //a에 저장된 정수값 10
printf("%d", *ap); //ap(ap의 실체:52)가 가리키는 곳에 저장된 값 10(*ap=&a)
printf("%u", &a); //a의 시작주소값 52번지
printf("%u", ap); //ap에 저장된 주소값 52번지
printf("%u", &ap); //ap의 시작주소값 48번지
연습문제1
- 포인터를 사용하여 두 변수의 값을 바꾸는 프로그램(=치환 프로그램)
포인터로 다른 함수의 기억공간을 사용
- assign함수가 main함수의 cheoli변수를 사용하기 위해서는 메모리에서의 위치(포인터)를 알아야 한다.
#include <stdio.h> void assign(); int main() { int cheoli = 0; assign(&cheoli); //포인터를 구해서 전달인자로 넘겨준다. printf("함수가 호출된 후에 cheoli에 저장된 값 : %d\n", cheoli); //100출력 return 0; } void assign(int *ip) //포인터변수를 선언하여 포인터를 받는다. { *ip = 100; }
※ 내가 넘겨주는 타입이 포인터라면 받을려고 하는 변수도 포인터이어야 한다.
함수의 한계를 극복한다.
- 함수는 전달인자가 많아도 리턴되는 값은 오직 하나이다.
- 따라서 메인함수에 있는 두 변수의 값을 바꾸는 함수는 포인터를 사용해야 한다.
연습문제2
- 함수를 호출하여 세 변수의 값을 정렬하는 프로그램
int in;
int *ip = ∈
printf("int형 변수의 포인터 크기 : %d\n", sizeof(&in));
printf("int형 변수를 가리키는 포인터변수의 크기 : %d\n", sizeof(ip));
-포인터와 포인터변수의 크기는 가리키는 자료형과는 관계없이 항상 같다.(4byte)
char ch;
int in;
double dp;
char *cp = &ch;
int *ip = ∈
double *dp = &db;
printf("%d, %d, %d\n", sizeof(cp), sizeof(ip), sizeof(dp)); //4, 4, 4
printf("%d, %d, %d\n", sizeof(*cp), sizeof(*ip), sizeof(*dp)); //1, 4, 8
int *ip;
double dp = 6.5;
ip = &dp;
※ 컴파일 에러 -> error C2440: '=' : cannot convert from 'double *' to 'int *'
-자동 형변환이 가능하다면 정수값이 저장된 기억공간에서 실수값을 참조하는 오류를 범하게 될 것이다.
-포인터의 형변환 규칙은 함수의 전달인자와 매개변수 사이에도 적용된다.
int in;
void func(int *ip);
func(&in);
int형 변수의 포인터 -----> int형 변수를 가리키는 포인터 변수