java
, c#
등 기본 자료형을 제외한 모든 것은 사실 포.인.터int
포인터(저장된 주소로부터 4바이트), char
포인터(저장된 주소부터 1바이트) *
를 붙인다.&
*
(역 참조 연산자)int num = 123;
int* num_address = # // int형 num 값이 저장된 주소값을 가리키는 포인터 num_address
printf("%p", &num); // 0x00DF0213 <- 123이 저장된 주소값 반환
printf("%p", num_address); // 0x00DF0213 <- num_address = &num
printf("%p", &num_address); // 0x00FA0255 <- 0x00DF0213이 저장된 주소값 반환
printf("%d", *num_address); // 123 <- num_address에 저장된 주소값에 저장된 값
A, B 코드의 차이점
매개변수를 받아서 두 매개변수의 값을 변경하려는 코드
A
#include <stdio.h>
int swap(int num1, int num2){
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
int main(void){
int num1 = 20;
int num2 = 10;
printf("num1 : %d, num2 :%d\n", num1, num2);
swap(num1, num2);
printf("num1 : %d, num2 :%d\n", num1, num2);
return 0;
}
B
#include <stdio.h>
int swap(int* num1_address, int* num2_address){
int temp;
temp = *num1_address;
*num1_address = *num2_address;
*num2_address = temp;
}
int main(void){
int num1 = 20;
int num2 = 10;
printf("num1 : %d, num2 :%d\n", num1, num2);
swap(&num1, &num2);
printf("num1 : %d, num2 :%d\n", num1, num2);
return 0;
}
포인터가 유효하지 않은 주소를 가리키는 것
함수의 지역변수 주소를 리턴값으로 사용한다면?
/* 안 좋은 사용 예 */
int* add(int a, int b){
int result;
result = a + b;
return &result;
}
int main(void){
int* result;
result = add(10, 20);
}
아무것도 가리키지 않는 포인터
NULL포인터 = 값이 0인 주소 = 0으로 채워진 비트패턴 = 하드웨어에서 존재하지 않는 주소
포인터 변수와 NULL
비교 가능 (포인터 변수와 0도 비교 가능하지만, 가독성에 좋지 않은 코드)
좋은 코딩 표준
NULL
을 반환할 수도 있는 경우라면 매개변수이름, 함수이름에 명시할 것NULL포인터 사용법
NULL
포인터인지 체크 모든 포인터는 동일한 크기를 가짐 (메모리 주소의 데이터크기는 동일하기 때문에)
보통 32bit 컴퓨터는 4바이트, 64bit 컴퓨터는 8바이트
배열의 이름은 사실 배열이 저장된 메모리의 시작 주소 (초기화 이후 주소 값을 변경할 수 없다.)
int nums[4] = {1,2,3,4};
int* ptr = NULL;
ptr = nums;
ptr = &nums[0]; // 위에 2개는 사실 같은 의미
ptr = nums[0]; // 컴파일 오류, 주소값을 저장해야됨
포인터에 덧셈 뺄셈으로 배열의 요소에 접근할 수 있다.
int main(void){
int num = 10;
int* num_address = #
printf("%p\n", num_address);
printf("%p\n", num_address+1);
}
+1을 했는데 왜 4만큼 더해졌지?
int main(void){
int nums[3] ={1,2,3};
int* ptr = nums;
printf("%d %d %d\n", nums[1], nums[1], *(ptr + 1));
}
위 코드는 모두 같은 값을 출력한다.
근데 만약 주소값을 정말 1바이트만 옮기고 싶다면 어떻게 할까
(char*)
포인터 변수앞에 이렇게 붙여주면 char형 데이터를 읽는 것 처럼 포인터 변수를 바꿔주겠다는 의미다. 포인터변수들을 담는 배열
배열의 주소들을 배열 형태로 저장해서 배열의 배열 형태로 사용할 수 있다.
int num1[3] = {11, 22, 33};
int num2[1] = {90};
int num3[4] = {88, 36, 47, 22};
int* num_pointers[3];
num_pointers[0] = &num1;
num_pointers[1] = &num2;
num_pointers[2] = &num3;
const
는 변수에 저장된 값을 변경하지 못하도록 하는 명령어
포인터 변수에서 const
는 저장된 메모리 주소, 주소가 가리키는 값 2가지를 보호하는 용도로 사용가능하다.
int* const p = # // 주소를 보호할 때
const int* p = # // 값을 보호할 때
const int* const p = # // 주소도 값도 보호할 때
포인터의 포인터 (주소를 저장하는 변수의 주소를 저장하는 변수..!)
2차원 배열이 사실 이중포인터와 비슷하다 (배열의 포인터, 각 배열도 포인터)
int main(int argv, char* argv[])
int main(int argv, char** argv)
int num = 10;
int* p = #
int** pp = &p;
연습
int num = 10;
int* p = #
int** pp = &p;
printf("%d\n", num);
printf("%p\n", p);
printf("%d\n", *p);
printf("%p\n", &p);
printf("%p\n", pp);
printf("%p\n", *pp);
printf("%p\n", &pp);