Programming
[C언어] 포인터
아나엘
2022. 11. 9. 17:33
Pointer
주소를 가지고 있는 변수
메모리의 구조
- 변수는 메모리에 저장된다.
- 메모리는 바이트 단위로 액세스됨.( 첫번째 바이트의 주소는 0, 두번째 바이트는 1,..)
- 변수의 크기에 따라 차지하는 메모리 공간이 달라짐
- char 형 변수: 1바이트, int형 변수: 4바이트, float형 변수 : 4바이트
- 변수의 주소를 계산하는 연산자: & (&i -> 4, &c -> 8, ..; 시작점)
포인터의 선언 및 변수와의 연결
int i = 10;
int *p;
p = &i;
다양한 포인터의 선언
char c = 'A';
float f = 36.5;
double d = 3.141592;
char *pc = &c; //문자를 가리키는 포인터 pc
float *pf = *f; //실수를 가리키는 포인터 pc
double *pd = &d; //실수를 가리키는 포인터 pc
간접 참조 연산자 *
포인터가 가리키는 값을 가져오는 연산자(&가 주소를 반환한다면,...)
int i =10;
int *p;
p = &i;
printf("%d", *p);
예제#1
#include <stdio.h>
int main(void){
int i = 3000;
int *p = &i;
printf("&i = %u\n", &i); //변수의 주소 출력
printf("i = %d\n", i); //변수의 값 출력
printf("*p = %d\n", *p); //포인터를 통한 간접 참조 값 출력
printf("p = %u\n", p); //포인터의 값 출력
return 0;
}
# result
# &i = 1245024
# i = 3000
# *p = 3000 //포인터가 가리키는 값. 간접참조.. 이걸 통해 변수의 값도 변경이 가능함
# p = 1245024
초기화가 안 된 포인터를 사용하면 안 됨. 즉 바로 *p=100 이렇게 쓰면 안 되고, int *p p = &i 이 이후에 사용 가능. 만약 아무것도 가리키고있지 않다면 NULL로 초기화.
또한 포인터의 타입과 변수의 타입도 일치해야 함.
포인터 연산
- 가능한 연산: 증가, 감소, 덧셈, 뺄셈
- 증가연산: 증가되는 값은 포인터가 가리키는 객체의 크기임.
- p++-> char, int, ... 에 따라 증가되는 값이 다름.
간접 참조 연산자와 증감 연산자
- *p++;
- p가 가리키는 위치에서 값을 가져온 후, p를 증가시킨다. 즉 p가 가리키는 값을 v에 대입한 후 p를 증가시킴
- (*p)++;
- (p가 가리키는 위치의 값)을 증가시킨다.
- *++p;
- p를 증가시킨 후 p가 가리키는 값을 v에 대입.
- ++*p;
- p가 가리키는 값을 가져온 후 그 값을 증가하여 v에 대입.
포인터의 형변환
꼭 필요한 경우 명시적으로 포인터의 타입을 변경할 수 있다.
double *pd = &f;
int *pi;
pi = (int *)pd;
포인터와 배열
- 배열과 포인터는 아주 밀접한 관계임.
- 배열 이름이 바로 포인터임
- 포인터는 배열처럼 사용 가능.
- (이해 안 되기 시작)
- 인덱스 표기법을 포인터에 사용 가능.
#include <stdio.h>
int main(void){
int a[] = { 10, 20, 30, 40, 50};
printf("&a[0] = %u\n", &a[0]);
printf("&a[1] = %u\n", &a[1]);
printf("&a[2] = %u\n", &a[2]);
printf("a = %u\n", a);
return 0;
}
#include <stdio.h>
int main(void) {
int a[] = {10,20,30,40,50};
printf("a = %u\n",a);
printf("a + 1 = %u\n", a+1);
printf("*a = %d\n",*a);
printf("(a+1) = %d\n",*(a+1));
return 0;
}
#a = 1245008
#a+1 = 1245012
#*a = 10
#*(a+1) = 20
포인터를 배열처럼 사용.. 배열은 결국 포인터로 구현된다. 또 포인터를 통해 배열 원소를 변경 가능.
포인터를 사용한 방법의 장점
포인터가 인덱스 표기법보다 빠릅.
왜냐? 인덱스를 주소로 변환할 필요가 없기 때문.
sum += a[i]; 대신 sum += *p++;
영상처리에 활용해보쟈
디지털 이미지는 배열을 사용해 저장되는데,,, 속도를 빠르게하기위해 포인터를 사용한다! 그래서 빠르구나
이미지 내의 모든 픽셀의 값을 10씩 증가시키는 예제
#include <stdio.h>
#define SIZE 5
void print_image(int image[][SIZE]) {
int r,c;
for(r=0;r<SIZE;r++){
for(c=0;c<SIZE;c++){
printf("%03d", image[r][c]);
}
printf("\n");
}
printf("\n";
}
void brighten_image(int image[][SIZE]) {
int r, c;
int *p;
p = &image[0][0];
for(r=0;r<SIZE;r++){
for(c=0;c<SIZE;c++){
*p += 10;
p++; //포인터닷
}
}
}
int main(void){
int image[5][5] = {
{10,20,30,40,50},
{10,20,30,40,50},
{10,20,30,40,50},
{10,20,30,40,50},
{10,20,30,40,50},
{10,20,30,40,50}};
print_image(image);
brighten_image(image);
print_image(image);
return 0;
}
인수 전달 방법
함수 호출 시에 인수 전달 방법
- 값에 의한 호출( call by value): 함수 호출 시 변수의 값을 전달해주는 것. 값만을 복사
- 참조에 의한 호출(call by reference): 포인터를 이용하여 흉내낼 수 있다. 변수의 주소를 함수의 매개 변수로 전달.
- swap() 함수(call by value): 변수 두 개의 값을 바꾸는 작업을 함수로 작성
#call by value 방식: 값만 복사
#include <stdio.h>
void swap(int x, int y);
int main(void){
int a = 100;, b = 200;
swap(a,b);
return 0;
}
void swap(int x, int y){
int tmp;
tmp = x;
x = y;
y = tmp;
}
#포인터를 이용
#include <stdio.h>
void swap(int x, int y);
int main(void){
int a = 100, b = 200;
swap(&a, &b);
return 0;
}
void swap(int *px, int *py){
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
제일 이해 안됨
scanf()함수
변수에 값을 저장하기 위해 변수의 주소를 받음
? 주소를 받는다......값을 저장..아!알았다
#include <stdio.h>
//기울기와 y절편 계산
int get_line_param(int x1, int y1, int x2, int y2, float *slope, float *yintercept){
if(x1==x2)
return -1;
else{
*slope = (float)(y2-y1)/(float)(x2-x1);
*yintercept = y1 -(*slope)*x1; //이걸 반대로 밖으로 전달해주는구만!!!!!!
return 0;
}
}
int main(void){
float s, y; //일단 변수를 주고
if(get_line_parameter(3,3,6,6,&s,&y)==-1)
print("에러\n");
else
printf("기울기는 %f, y절편은 %f\n", s,y);
return 0;
}
배열 매개 변수
- 일반 매개 변수: 매개변수 x에 기억 장소가 할당됨.
- 배열 매개 변수: b에 기억 장소가 할당되지 않음. 왜냐하면 배열을 함수로 복사하려면 시간 오래걸림.
화물이 너무 크면 화물 전체를 x, 주소만 전달하는 수 밖에..
포인터 반환 시 주의점
- 함수가 종료되더라도 남아있는 변수의 주소를 반환해야 함.
- 지역 변수의 주소를 반환하면, 함수가 종료되면 사라지기 때문에 오류가 난다.
오? 그러면.. 함수 종료되면서 result는 사라지니까 그럼 우째
반응형