10. 메모리의 원하는 번지에 직접 값을 쓰는 경우가 있습니다.
하드웨어를 직접 제어하는 경우, 많이 사용합니다.
예) 0x378 번지의 값이 1이면 USB가 살아있다.
char *alive = (char *) 0x378;
if (*alive == 1) {
//USB가 살아 있구나. 뭘 하지?
} else {
//USB가 안 살아있음, 다른 일을 하자.
}
12. 지난 시간에 우리 마음대로 사용할 수 있는 heap 이라고
하는 공간이 있다고 했습니다.
이 공간을
배정받는 함수
malloc()
calloc()
반납하는 함수
free()
13. void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t n, size_t size);
우리가 요청한 크기만큼 힙에 공간을 할당해 줍니다.
리턴값은 요청한 공간의 시작주소입니다.
free함수는 할당한 메모리를 해제할 때 사용합니다.
할당하고 해제하지 않으면 leak이 발생할 수 있습니다.
14. 예제) int 크기만큼 공간을 할당받고 싶어요.
//NAVER cast void * to int * in this case!
int *ptr = malloc(sizeof(int));
*ptr = 50;
printf("%dn", *ptr);
free(ptr);
15. 예제) int 3개만큼 동적 할당을 하고 싶어요.
*포인터의 덧셈이 잠깐 나왔습니다.
int *ptr = malloc(sizeof(int)*3);
int *temp;
*ptr = 10;
temp = ptr + 1;
*temp = 20;
printf("%dn", *ptr); //10
printf("%dn", *(ptr + 1)); //?
16. 예제) calloc을 사용해 봅시다.
*포인터의 덧셈이 잠깐 나왔습니다.
int *ptr = calloc(3, sizeof(int));
int *temp;
*ptr = 10;
temp = ptr + 1;
*temp = 20;
printf("%dn", *ptr);
printf("%dn", *(ptr + 1));
27. void foo(int *i) {
*i = *i + 10;
}
int main(void) {
int a = 100;
foo(&a);
printf("%dn", a);
return 0;
}
//실행 결과
200
28. int 변수에 대해 call by reference 를 하기 위해서
int * 를 사용했습니다.
char 변수의 call by reference를 하려면?
double 변수의 call by reference를 하려면?
int* 변수의 call by reference를 하려면?
29. int 변수에 대해 call by reference 를 하기 위해서
int * 를 사용했습니다.
char 변수의 call by reference를 하려면? char *
double 변수의 call by referenc를 하려면? double *
int* 변수의 call by reference를 하려면? int **
30. int myalloc(int *ptr, unsigned int size)를 구현합니다.
- int 전용 동적할당 함수
- 성공하면 size, 실패하면 -1을 리턴
int myalloc (int *ptr, unsigned int numb) {
//implement
}
int main(void) {
int *ptr = NULL;
int ret = myalloc(ptr, 1);
if (ret == -1) return 1;
*ptr = 5054;
printf("%dn", *ptr);
return 0;
}
31. 어떻게 구현하든지 앞의 함수는 틀렸습니다.
argument로 전달한 ptr은 값이 바뀌지 않기 때문입니다.
int *를 call by reference로 호출하려면
int **를 사용합니다.
int myalloc (int **ptr, unsigned int numb) {
*ptr = malloc(sizeof(int) * numb);
if (ptr) return numb;
else return -1;
}
int main(void) {
int *ptr = NULL;
int ret = myalloc(&ptr, 1);
if (ret == -1) return 1;
*ptr = 5054;
printf("%dn", *ptr);
return 0;
}
34. C언어의 배열은 90% 정도 포인터랑 닮았습니다.
포인터에도 배열 연산을 그대로 쓸 수 있습니다!
int arr[5];
double b[]= {1, 2, 3, 4, 5}; //자동으로 5개가 됨
35. 이 코드를 실행해 보고 알아낸 사실을 토의해 봅시다.
int main(void){
int a[5] = {1,2,3,4,5};
printf("%pn", a);
printf("%p %dn", &a[0], a[0]);
printf("%p %dn", &a[1], a[1]);
return 0;
}
36. 놀랍게도 배열이름 변수에는
배열의 첫번째 원소의 주소가 들어갑니다!
arr = &arr[0]
int의 주소를 저장한 변수 = int *
포인터를 배열에 대입해서 쓸 수 있을까요?
37. HULL?
int main(void){
int a[5] = {1,2,3,4,5};
int *ptr = a; //not &a, &a[0]도 OK
printf("%pn", ptr);
printf("%p %dn", ptr, *ptr);
printf("%p %dn", ptr + 1, *(ptr +1));
return 0;
}
38. HULL?
무언가 수상하지요?
int main(void){
int a[5] = {1,2,3,4,5};
int *ptr = a; //not &a, &a[0]도 OK
printf("%pn", ptr);
printf("%p %dn", ptr + 0, *(ptr + 0));
printf("%p %dn", ptr + 1, *(ptr + 1));
return 0;
}
int main(void){
int a[5] = {1,2,3,4,5};
printf("%pn", a);
printf("%p %dn", &a[0], a[0]);
printf("%p %dn", &a[1], a[1]);
return 0;
}
39. HULL?
포인터가 미쳐 날뛰고 있습니다!!
int main(void) {
int a[5] = {1,2,3,4,5};
int *ptr = a;
printf("%pn", ptr);
printf("%p %dn", &ptr[0], ptr[0]);
printf("%p %dn", &ptr[1], ptr[1]);
return 0;
}
int main(void) {
int a[5] = {1,2,3,4,5};
printf("%pn", a);
printf("%p %dn", &a[0], a[0]);
printf("%p %dn", &a[1], a[1]);
return 0;
}
40. 사실 a[i] 는 *(a + i) 랑 완전히 똑같습니다.
사람의 편의를 위해 읽기 쉽게 만들어 준 거랍니다.
이런 걸 syntax sugar 라고 합니다.
a[i] = *(a + i)
*나중에 다시 나오지만 a->b도 syntax sugar 입니다.
41. 다 아는 산수 한 번 해볼까요?
a[3] = *(a + 3)
= *(3 + a)
= 3[a]
42. int main() {
int a[5] = {1,2,3,4,5};
for (int i = 0; i < 5; i++)
printf("%dn", i[a]);
return 0;
}
(형~오빠~, 이거 어디가 잘못된 건지 좀 가르쳐 주세요.)
잘못된 건 비뚤어진 너의 마음이다 ㅋㅋ.
죄송합니다.
된다고 절대 사용하면 안 됩니다.