[임베디드 C] 포인터

정재훈·2022년 3월 30일
0

임베디드 C언어

목록 보기
1/11
post-thumbnail

주소의 개념

모든 변수들은 주소가 존재합니다.

변수 : 특정 메모리영역에 써있는
&변수 : 특정 메모리영역의 위치(주소)
배열 : 배열 시작 메모리영역의 위치(주소) , index마다 4바이트씩 차이가 난다.

printf("%X",변수주소);를 통해 변수의 주소를 출력할 수 있습니다.

int의 주소는 4바이트지만 주소를 나타낼때는 맨 앞부분 주소만 사용

&a가 0x1000이면 &(a+1)은 0x1004이다.

Trace
중단점(Break Point) 좌측 바 클릭하거나 F9으로 하고,
F5로 trace 모드 진입,
F10으로 다음 브레이크 포인트로 이동

포인터

포인터 변수의 줄임말로 메모리 주소를 보관하는 변수, 변수를 가리킨다라고 생각하면 이해하기 편하다. 가리킨 영역의 값을 제어할 수도 있다.

*포인터 변수 = &변수(변수의 주소)

#include <stdio.h>

int main() {
	int x = 100;
	int *p = &x;
	int *g = &x;
	
    printf("%d\n",x); // 100
    
	*p = 5000;

	printf("%d\n",*g); // 5000
	printf("%d\n",x); // 5000

	return 0;
}

포인터 & 배열

배열의 이름은 배열의 시작 메모리 영역의 주소와 나타난다.
&arr[0] = arr

#include <stdio.h>

int main() {


	int arr[5] = {1,5,3,2,6};

	printf("%X\n", &arr[0]); // 61FF0C
	printf("%X\n", arr); // 61FF0C

	return 0;
}

포인터 변수에 배열의 첫 주소를 담을 수 있다.
*p = arr == *p = &arr[0]

줄임 표현식
(p+0) -> p[0];
(p+1) -> p[1];
(p+2) -> p[2];
(p+3) -> p[3];
*(p+4) -> p[4];

#include <stdio.h>

int main() {


	int arr[5] = {11,15,13,12,16};
	int *p;

	p = arr;

	printf("%d %d", arr[2], p[2]);  // 13 13

	return 0;
}

arr는 배열 시작의 메모리영역의 주소를 의미하기 때문에, arr[2]와 p[2]는 똑같은 의미입니다.

포인터의 자동 변환

#include <stdio.h>

void kfc(int abc[5])
{

	for(int i=0; i<8; i++)
	{
		printf("%d ", abc[i]); // 1 4 3 5 2 7 4 3

	}
}

int main() {


	int arr[] = {1,4,3,5,2,7,4,3};

	kfc(arr);

	return 0;
}

kfc라는 함수에는 정상적으로 arr의 주소를 받기 위해서는 int *abc와 같이 작성을 해줘야합니다.
하지만, C언어 내부적으로 초기화되지 않은 1차원 배열은 포인터로 자동 변환 됩니다.
int abc[5] => int *abc

2차원 배열 기본

2차원 배열은 가로 세로로 된 격자 형태가 아닌, 1차원 배열이 여러개가 모여있는 것이다.

배열의 이름은 배열 시작 메모리 영역의 주소
arr[0] : 가장 위에 있는 1차원 배열의 이름

#include <stdio.h>


int main() {


	int arr[2][3];

	printf("%X\n",arr); // 61FF08
	printf("%X\n", arr[0]); // 61FF08

}

arr[1] : 두번째 배열이름

#include <stdio.h>


int main() {


	int arr[2][3];

	printf("%X\n",arr[1]); // 61FF14
	printf("%X\n", &arr[1][0]); // 61FF14

}

2차원 배열 심화

#include <stdio.h>


int main() {


	int arr[2][3] ={
			{1,2,3},
			{6,7,8}
	};

	printf("%d\n",arr[0][5]); // 8
}

-------------------
int *p = arr;
printf("%d\n",p[5]); // 8

0 x 3 + 5 = 5번째 칸

Const

const = 상수 의미로 값을 바꿀 수 없으며, 포인터 변수 또한 마찬가지이다.
다른 곳을 가리킬 수 있지만, 가리킨 곳의 값을 변경할 순 없다.

#include <stdio.h>


int main() {


	int x = 10;
	int y = 123;
	const int *p = &x;

	p = &y; // 다른 주소 가리키기 가능
    // p = 123 와 같이 값을 변경할 수는 없음

	printf("%d", *p);


	return 0;
}

문자열 초기화

초기화 방법 1 : char v[4] = "ABC"
초기화 방법 2 : const char *p = "ABC" : 문자 길이만큼의 배열을 지정해주지 않아도 된다.

#include <stdio.h>


int main() {


	char *p = "ABC";

	for(int i=0; i<3; i++)
	{
		printf("%c ", p[i]);  // A B C
	}


	return 0;
}

변경 가능 vs 변경 불가능

방법 1은 변경 가능 , 방법 2는 변경 불가능
변경 가능

#include <stdio.h>

void abc(char *p)
{
	p[1] = 'Z';
}

int main()
{
	char arr[4] = "ABC";
	abc(arr);

	printf("%s",arr); // AZC

	return 0;
}

변경 불가능

#include <stdio.h>

void abc(char *p)
{
	p[1] = 'Z';
}

int main()
{
	char *arr = "ABC";
	abc(arr);

	printf("%s",arr); // 에러 발생

	return 0;
}

다중 문자열 다루기

char *vs[3] = {"ABCDE", "BTS", "KK"}; : 문자 길이만큼의 배열을 지정해주지 않아도 된다.

출력

#include <stdio.h>

int main()
{
	char *vs[3] = {"ABCDE", "BTS", "KK"};

	printf("%s",vs[0]); // ABCDE


	return 0;
}

읽기 전용 문자열

const char *ts[3][6] = {"ABCDE", "BTS", "KK"}; : 글자 변경 불가

정리

주소 - 주소를 담는 변수는 &이다.
배열의 이름은 배열의 주소를 의미한다. ex) arr = &arr[0]
ex) arr[3] = {1,2,3} 이라고 한다면 arr[0]는 을 나타내고 &arr[0]은 주소를 나타낸다.

포인터 - 주소를 가리키는 변수 *를 사용합니다.
포인터는 을 가리킬 수 없고 주소를 가리킬 수 있습니다.
불가 *p = arr[1];
가능 *p = &arr[1];

profile
여러 방향으로 접근하는 개발자

0개의 댓글