Pointer
추적
주소 | 값 |
1284EA43 | 71 (**a) |
125F7458 | 1284EA43 (*a) |
122EF560 (&a) | 125F7458 (a) |
②→
①↖
포인터는 1 2 순서로 이동하며 따라가면 편하다.
포인터는 주소, 0차, 1차, 2차, ...로 생각하면 편하다.
주소 | 0차 | 1차 | 2차 |
&a | a | *a | **a |
122EF560 | 125F7458 | 1284EA43 | 71 |
포인터를 지원한다는 것은 어떤 변수에 대해 ``c &``연산을 통해 변수의 주소를 구할 수 있음을 의미한다.
자바도 참조개념을 사용하지만 포인터를 지원하지 않는다고 하는 것은 이런 맥락에서다.
포인터 배열과 배열 포인터
int *p[4]; // 포인터 배열. [주소, 주소, 주소, 주소]
int (*p)[4]; // 배열 포인터. [크기 4인 배열의 주소를 담고있는 포인터]
배열 포인터의 경우 접근할 때도 (*p)[i] 로 접근해야 한다.
```
포인터 배열은 포인터들의 배열이다. (이 때 배열 그 자체가 포인터이기 때문에 헷갈릴 수 있다.)
배열 포인터는 배열을 가리키는 포인터다.
Parameter에 ``c int **p``로 적는 경우, 배열의 크기가 12라 했을 때 3*4인지 6*2인지 알 수 없기 때문에
column값을 명시해서 행 열을 구분할 수 있도록 적어야 한다.
```c
int *p[4]
int p[][4]
```
row에 쓰면 안되고 무조건 column에 써야하는데, 효율성 때문인 것 같다.
row값을 명시하면 결과적으로 실제 값이 저장되어있는 메모리 공간에 접근했을 때 column이 몇인지 모르니 어디까지 읽어야할지 모르는건 똑같다.
그래서 row와 배열의 크기를 이용해 column을 얻기 위해 함수에서 배열의 크기를 다시 계산하는 과정이 필요하니까 그냥 column을 넘기도록 하는 듯.
pointer 변수의 주소
```c
단일 pointer일 경우 ( struct *p ) p != p[0] 이고,
이중 pointer일 경우도 ( struct **p | struct *p[] ) p != p[0] 이다.
```
두 경우 모두 ``c *p == p[0]`` 이며, ``c p->m1 == p[0].m1`` 이다.
배열을 포함하여 그 어떤 경우도 ``c type == type[0]`` 인 경우는 없으며 ``c type == &type[0], *type == type[0]`` 이다.
즉, pointer와 data는 분리되어 있다.
연산자 우선순위는 [] > *
*와 []의 차이 - &연산
002DF7EC | kbc |
- 포인터의 경우 ``c &``하면 `` p``변수의 주소가 되고, +1하면 메모리의 주소 단위의 +1이므로 실제로는 +4가 된다.
- 배열의 경우 ``c &``하면 배열 객체 자기자신을 의미하게된다.(sizeof 연산도 마찬가지다.)
따라서 +1하면 배열의 크기 단위의 +1이므로 실제로는 배열의 크기인 +16( 0x10 )이 된다.
*와 []의 차이 - stack seg, data seg
- ``c s[]``는 stack에 잡혀 언제든지 수정 가능하지만, ``c *s``는 "Hello" 문자열이 data seg에 잡혀 수정이 불가능하다.
- ``c *s``는 가리키는 곳만 다른 문자열로 변경하면 되므로 ``c s="world";`` 같은 식으로 변경이 가능하지만, ``c s[]``로 선언했을 때, ``c s="world"`` 하면 오류가 발생한다.
``c s[]``는 stack에 공간이 할당되어 있고 그 공간만 참조하므로 ``c strcpy()``를 이용해 해당 공간에 문자열을 덮어 써야 한다. - ``c *s``도 ``c malloc()``으로 heap에 공간을 잡는다면 ``c s[3]='2';`` 같은걸로 초기화/입력이 가능하지만 어차피 ``c s = malloc()`` 한다는건 heap을 가리키면서 기존에 가리키고 있던 문자열은 버린다는 의미다.
함수도 포인터
function pointer
- ``c #pragma comment()`` 같은건 compiler에 의존적인 전처리 명령어다.
따라서 compiler로 visual C가 아니라 gcc를 사용하는 Dev C++같은 건 못알아 먹어서,
project option의 parameter tap을 이용하는 등 옵션을 따로 사용해야한다.
asm이나 SEH가 제대로 안되는 것도 gcc가 이를 지원하지 않기 때문. - ``c hook_by_code("ntdll.dll", "ZwQuery", (PROC)NewZwQueryInformation);``
``c (PROC)NewZwQueryInformation``같이 함수 자체를 파라미터로 넘기는 건, 함수의 주소를 넘기는 것으로
함수 포인터를 넘기는거랑 같다고 보면 된다. 어차피 함수 포인터도 함수를 가리키는 거니까.
함수도 변수처럼 어떤 공간에 "선언 및 할당"되어 있는 것이다.
'Languages & Frameworks > C C++' 카테고리의 다른 글
exec 계열 함수 (0) | 2017.05.01 |
---|---|
fork - exec / wait +clone (0) | 2017.05.01 |
Assembly (0) | 2016.11.18 |
[C] printf, scanf계열 (0) | 2016.11.10 |
[C] atoi / strtol , sprintf : 문자열 > 숫자, 16진수 변환 (2) | 2016.11.06 |