``c <stdint.h>``를 사용하도록 하자.

``c int``보다 ``c uint8_t`` 같은 고정 크기 타입을 사용하는 것이 좋다.

``c char``보다 ``c TCHAR``를 사용하는 것이 좋다. 윈도우인 경우 컴파일 옵션에 따라 리눅스 등에서도 호환 가능하기 때문.


Types

```c

uintptr_t

```

포인터를 대상으로 덧셈, XOR 등 수치 연산이 필요한 경우 포인터를 숫자값으로 취급하기 위해 사용하는 타입.
어떤 포인터라도 담을 수 있는 크기의 데이터 타입이라는 의미가 된다.
따라서 포인터를 대상으로 수치 연산이 필요한 경우 사용한다.
``cpp (uintptr_t)this + 4`` 이렇게 더하기 연산을 해도 1씩 증가하기 때문에, `` uint8_t*``같은 것으로 변환하는 것 보다 더 낫다. `` uint8_t*``로 변환하면 + 같은건 되는데 ``c % / *`` 연산자에서 에러난다.

```c

(void *)

```

단순히 어떤 것을 가리키는 포인터 일 경우 사용한다.
``c uintptr_t``와 달리 원래의 type으로 다시 cast했을 때 제대로 동작함을 보장해준다.

```c

size_t

```

배열 선언 시 할당할 수 있는 원소 수의 최댓값을 의미한다.
따라서 배열 원소 수의 최댓값에 사용한다.

Type Casting

타입 캐스팅을 적절히 해주지 않으면 계산에서 오류가 발생한다. 특히 포인터가 그렇다.

``c printf()``할 때도 마찬가지.


source : 

```c

chunk0_ptr[1] = (uint64_t) &chunk0_ptr - (3*sizeof(uint64_t));

printf("chunk0_ptr[1] : %p / &chunk0_ptr - 3 : %p\n", 

    chunk0_ptr[1], &chunk0_ptr - (3*sizeof(uint64_t)));

```

result : 

```

chunk0_ptr[1] : 0x602050 / &chunk0_ptr - (3*sizeof(uint64_t)) : 0x601fa8

```

이런 식으로 대입할 때와 같은 값을 출력하도록 했는데 다른 값이 출력되는 이유는, 

``c &chunk0_ptr``은 주소이므로 ``c -1`` 당 ``c -8``이 되기 때문. ( 64bit OS )

따라서 ``c - (3*sizeof(uint64_t)) ==> - 8*(3*sizeof(uint64_t))`` 이 되어버린다.


이를 방지하려면 대입할 때와 동일하게 형변환을 해주거나, 형변환을 하지 않으려면 ``c -3``만 빼주어야 한다.

```

chunk0_ptr[1] : 0x602050 / (uint64_t) &chunk0_ptr - 3*(sizeof(uint64_t)) : 0x602050

chunk0_ptr[1] : 0x602050 / &chunk0_ptr - 3 : 0x602050

```


~0u

``c ~(uint)0``과 같다. 따라서 ``c 0xffffffff``가 된다.

가변 인자

```c
#include <stdarg.h>
int __printf (const char *format, ...)
```
  • 가변 인자 함수를 만들기 위해서는 `` stdarg.h``가 필요하다.
  • 반드시 1개 이상의 고정 파라미터가 있어야 한다.
  • `` ...``은 파라미터 가장 뒤에 위치해야 한다.
대충 이런 식으로 동작한다.
```c
int va_func(int args, ...) {
    va_list ap;
    va_start(ap, args);    // ap가 가변 인자 리스트를 가리키도록 대입.
    int arg = va_arg(ap, int);
    va_end(ap);
```

const

파라미터로 받는 변수가 실제로는 상수가 아니지만, 함수 내부에서 변경하지 못하도록 설정하고 싶은 경우 ``c const``를 활용할 수 있다.
```c
int f(const int a){
    a = 3; // compile time error
}
```


const type *ptr / type * const ptr

```c

int a = 3;

int b = 5;

const int *ptr = &a;

ptr = &b;    // right

*ptr = 10;    // error

```

``c const int``를 가리키는 포인터. 따라서 ``c *ptr``을 수정할 수 없다.

이 때 가리키고 있는 대상이 ``c const``가 아니어도, ``c ptr``로 접근하는 경우는 수정 불가능하다.


```c

int a = 3;

int b = 5;

int * const ptr = &a;

ptr = &b;    // error

*ptr = 10;    // right

```

``c int *``를 가리키는 ``c const`` 포인터. 따라서 ``c ptr``을 수정할 수 없다.