C Pointer ?

·2022년 11월 9일
0
post-thumbnail

포인터가 머에요 ㅠㅠ

포인터란? 포인터는 변수의 메모리 공간주소를 가리키는 변수이다.
포인터를 사용하면 프로그래밍 언어에서 메모리를 직접적으로 다루기 때문에 커널, 운영체제 개발, 응용프로그램의 취약점을 찾는 등 컴퓨터에 대해 low-level적인 접근을 할 수 있다.

C에서 포인터를 만들 때 포인터 변수 이름 앞에 *을 붙이고 선언 할 때 일반 변수 앞에 &를 붙여 메모리 주소 값으로 선언한다.
반대로, 포인터가 가리키는 값을 가져오는 것을 역참조 라고 한다.
C에서 역참조를 할때는 포인터 변수 앞에 *을 붙여 메모리 주소에 접근하여 값을 가져온다.

포인터를 사용하여 연산을 할 수 있다.
포인터 연산은 포인터 변수에 +, - 연산자를 사용하여 값을 더하거나 뺀다.
또는 증감식을 통해 값을 증가 시키거나 감소 시킬 수 있다.

int형 포인터 변수가 있다 하자.
int형 포인터 변수에 +1을 하였다. 그러면 포인터 배열의 주소값은 +1이 증가하는 걸까? 아니다. 포인터 연산은 포인터 변수의 자료형 사이즈 만큼 곱해져서 연산된다.

ex). double형 nPtr의 메모리 주소 값이 = 0x00000000일때 nPtr += 2이면 nPtr의 변경된 메모리 주소 값은 0x00000010(16)이다.

포인터 변수는 데이터의 위치를 CPU의 메모리 주소값으로 처리한다.
변수나 기타 하드웨어의 레지스터는 CPU의 주소로 표현 된다.

따라서 포인터 변수는 모두 주소값을 취급하는 것으로 CPU의 메모리 공간에 따라 길이와 처리 방식이 결정 된다.
CPU가 결정 되면 CPU에 의존하여 길이가 결정되고 한개의 CPU 내에서도 메모리 공간에 따라 길이가 달라 질 수 있다.

ex)
1. 16비트 CPU -> 16비트 어드레스 방식 -> 포인터 길이 2바이트 sizeof(int*) = sizeof(char*) = sizeof(void*) = ... = 2
2. 32비트 CPU - 32비트 어드레스 방식 -> 포인터 길이 4바이트 sizeof(int*) = sizeof(char*) = sizeof(void*) = ... = 4

이러한 포인터을 유용하게 활용 할 수가 있다.
그 예제로는 배열, 구조체 포인터들이 있다.

배열 포인터: 배열을 가르키는 포인터 변수이다.

// char *를 저장하는 배열이다. (char 배열을 배열함)
char *str[] = {"고양이", "키우고", "싶어요"}; 

for (int i=0;i<3;i++) 
	printf("%s\n",str[i]); //char 배열을 출력한다.

구조체 포인터: 구조체를 가르키는 포인터 변수이다.

struct Struct { int member }; // 구조체 선언
struct Struct *p = malloc(sizeof(struct Struct)); // 구조체 포인터 선언

p->member = 2020; // 화살표 연산자로 구조체 맴버에 2020 값 할당
printf("Struct.member: %d", p1->member); // 화살표 연산자로 구조체 맴버에 할당한 값 출력

그래서 머라는거임!

1번글: https://modoocode.com/23

문제 1. * 와 & 연산자의 역할이 무엇인지 말해보세요.

* 연산자란?

  1. 변수 뒤에 붙이면 곱셈을 한다.
  2. 변수를 선언할 때 변수 앞에 *을 붙이면 그 변수는 포인터 변수가 된다.
  3. 포인터 변수 앞에 *을 붙이면 그 주소의 해당하는 값을 참조한다.

실행 결과:

& 연산자란?

  1. 변수 뒤에 붙이면 AND 연산을 한다.
  2. 변수 앞에 붙이면 변수를 역참조한다. (변수의 주소 값을 가져온다)

실행 결과:

문제 2. int **a; 와 같은 이중 포인터(double-pointer) 에 대해 생각해 보세요.

이중 포인터는 포인터 변수의 포인터 변수이다. (?)
말 그대로 포인터 변수를 포인트 해준다. 그래서 이중 포인터 변수를 한 번 참조하면 포인터 변수의 주소가 나오고 두 번 참조해야 a의 값이 나온다.

실행 결과:

추가로, 이중 포인터 변수의 크기는 포인터 변수의 주소를 저장하기 때문에

32bit - 4byte, 64bit - 8byte가 된다.

실행 결과:


2번글: https://modoocode.com/24

문제 1. int arr[3][3]; 과 같은 배열은 내부적으로 어떻게 처리되는지 생각해보세요.

실행결과를 보니 내부적으로는 한줄로 쭉 나열된 느낌이다.

실행 결과:

그래서 2차원 배열 포인터는 이렇게 참조할 수 있다.

실행 결과:

추가로, 배열 범위를 초과하면? 항상 쓰레기 값이라고만 알고 있었지만? 스택 주소값이 출력될 수도 있다!

실행결과:

문제 2. int* arr[3]; 과 같은 배열이 가지는 의미는 무엇일까요?

int *의 배열이므로 포인터들의 배열이다.
64bit 시스템의 포인터 배열의 크기는 8byte 이므로 이 배열의 크기는 24byte이다.

실행 결과:

0개의 댓글