Home > C > Basics > [C언어의 기본]포인터와 배열

[C언어의 기본]포인터와 배열

포인터

포인터란? 주소 값 저장을 목적으로 선언되는 포인터 변수

int main(void)
{
	char ch1 = 'A', ch2 = 'Q';
	int num = 7;
	...
}

이 구문을 보면 메모리 할당이 A 1칸 / 7 n칸이 되는데 n칸중 제일 앞에 칸이 주소(int형 특징)가 된다.

| 1칸 | 2칸 | 3칸 | 4칸 |
| —- | —- | —- | —- |

이렇게 4bit의 칸이 있다고 한다면 제일 앞에 1칸이라는 단어가 주소가 된다는 것이다.

즉, 포인터는 0x12ff76과 같이 저장된다 (주소값)

포인터는 상수와 변수 2가지의 형태가 있다.

연산자맛보기

정수 7이 저장된 int형 변수 선언, 이 주소값 저장을 위한 포인터 변수 pnum을 선언한다.
그리고 pnum에 변수 num주소 값을 저장한다.
int main(void)
{
	int num = 7;
	int* pnum; // 포인터 변수 선언
	pnum = # //주소값 이니까 붙히고 저장
}

이렇게 되면 pnum은 0x122ff76과 같은 주소값 형태가 되고

num=7인데, 그 앞에 값이 0x122f76이니까 즉 포인터는 7을 가르키고 있는 것이다.

| 0x122ff76 | 0x122ff77 | 0x122ff78 | 0x122ff79 |
| ——— | ——— | ——— | ——— |

7의 값이 이러면 앞에 0x122ff76이 주소값 이라는 것이다.

포인터 변수 선언

int* pnum1;
double* pnum2;
unsigned int* pnum 3;

//= > 기본공식 type * ptr;

포인터 변수선언은 (Type) * ptr;로 이루어진다.

포인터와 연산자

int num = 20
int ptr = &num
//가능하다 왜 ? 정수형에 정수변수를 넣었기 때문

int num = 20
int* ptr = *num;
but)
int ptr=
//* ptr 은 안됨  num에 대한 정보가 없어서

이것을 통해 타입이 필요한 이유를 알 수 있다.

실제로 int형은 4byte, doulbe형은 8byte다.

이러한 형태를 맞추지 않으면 8byte에 4byte가 들어가서 이상해진다.

형을 말해주지 않으면 불가능하다

컴퓨터 - “그래서 얘가 몇바이트 인데 인간”

int main(void)
{
	int num1 = 5;
	double* pnum1 = &num1; //불일치

	double num2 = 5;
	int* pnum2 = &num2; //불일치
}

이것을 보면 메모리는 int형인데 포인터에게 난 8byte인데? 라고 해서

메모리를 오버하게 저장을 한다.

메모리 참조하는 *연산자

//포인터 변수를 가리키는 메모리 공간인 변수 num접근
=*pnum=20;

포인터 변수 pnum이 가리키는 메모리 공간인 변수 num에 정수 20저장
pnum이 가리키는 메모리 공간인 변수 num값을 출력
int main(void)
{
	int num1 = 100, num2 = 100;
	int* pnum;

	pnum = &num1;    // 포인터 pnum이 num1을 가리킴
	(*pnum) += 30;     // num1+=30과 동일

	pnum = &num2;     // 포인터 pnum이 num2를 가리킴
	(*pnum) -= 30;     // num2-=30과 동일

	printf("num1:%d, num2:%d \n", num1, num2);
	return 0;
}

이 예시를 보면 num=100으로 num2도 100으로 초기화되었고,

int * pnum을 하여 포인터 지정

첫 번째로, pnum에 &num1값을 가리킨다.

그 후 pnum값에 30을 누적

두 번째로, pnum에 &num2값을 가리킨다.

그 후 pnum값에 -30 누적

결과로 num1은 130, num2는 70이 된다.

여기서는 포인터를 통해 변수를 가리키는 지점을 변경시켜 관리한 것이다.

포인터 형의 존재 이유

포인터 형은 메모리 공간을 참조하는 기준이 된다.

int main(void)
{
	double num = 3.14;
	int* pnum = # //형 불일치
	printf("%d", *pnum); //의미없음
}

이 예시를 보면 double형을 지정 후 그 값의 포인터를 int형으로 지정했다.

출력을 한다고 한듯 그것은 의미가 없다.

컴파일러에서는 에러가 발생하지 않으면 출력이 되지 않는다.

왜냐하면 C언어는 유연함을 보장하지 위해서 그렇다.

포인터 기반의 메모리 접근 기준을 만들기 위해서 타입이 존재한다는 것을 알아두자!

문제

문제1: 예제 실행시 변수와 포인터 변수의 관계를 그림을 그려서 표현한다.
- 이것은 직접 그리는 거라... 넘긴다..!!ㅋㅋㅋ 블로그 못올림
문제2 : int형 변수 num1 num2을 선언해서 동시에 10 20을 초기화한다. (조건1)
int형 포인터 변수 ptr1 ptr2 선언하여 각각 num1 num2값을 가르킨다. (조건2)
이 상태에서 ptr1 ptr2를 이용해서 num1값 10증가 num2 값 10감소 시킨다. (조건3)
그리고 이 상태에서 가리키는 대상을 바꿔보자.(조건4)
int main(void)
{
    //조건1
	int num1 = 10;
	int num2 = 20;
	
    //조건2
	int * ptr1 = &num1;
	int * ptr2 = &num2;
	int * temp;

	printf("기본값 ptr1는 %d \n", *ptr1);
	printf("기본값 ptr2는 %d \n", *ptr2);

    //조건3
	(*ptr1) += 10;
	(*ptr2) -= 10;

	printf("추가값 ptr1는 %d \n", *ptr1);
	printf("뺸값 ptr2는 %d \n", *ptr2);

    //조건4
	temp = ptr1;
	ptr1 = ptr2;
	ptr2 = temp;

	printf("최종변환값 ptr1는 %d \n", *ptr1);
	printf("최종변환값 ptr2는 %d \n", *ptr2);
	return 0;
}

위를 보면 일단 바꿔치기 해야되니까 안전하게 temp를 써준다.

초기화를 한후 포인터 지정 그리고 체크를 위해서 한번 ptr1 과 ptr2값을 출력해준다.

그리고 그 값을 조건3에 맞춰서 한후 printf를 통해 추가값인지 뺀 값인지 체크

그리고 조건4를 통해 교차시킨후 최종변환값이라는 병목으로 바뀌었는지 체크한다.

잘못된 포인터의 사용과 Null 포인터

int* ptr; //쓰레기값 
*ptr = 200; //0x0010

자 이렇게 ptr값을 초기화를 해주지 않으면 쓰레기값이 들어가게 된다.

이때 포인터 ptr에 값을 집어 넣는다면 어떻게 될까?

=> 포인터가 “어..? 기존 쓰레기값이 어디있지?”하면서 문제가 생길 수 있다.

int* ptr1 = 0;
int* ptr2 = NULL;

그래서 포인터 변수를 초기화 할때는 0이나 Null값을 지정해준다.

다음은 엄청 길거같아서 이번은 짧게가고 다음은 길게 갈것같다.

다음은 포인터 + 배열 / 함수 이다.