본문 바로가기

프로그래밍/C language

5. Pointer and Arrays

5.1 Pointer and Addresses

- 메모리는 8byte크기를 갖는 cell들의 집합임. 예를 들어, char은 cell 1개, short는 cell 2개로 표현될 수 있음
- pointer는 이러한 것들의 address를 갖는 group of cell임
- unary operator인 &는 object의 address를 반환하는 함수
ex) p = &c
- unary operator인 *는 indirection 또는 dereferencing operator이며, 역참조를 뜻한다. 
즉, pointer가 변수 a를 참조했다면, pointer를 통해 역으로 변수 a를 참조한다는 것이다.
(ad. referencing의 의미는 a의 존재를 바탕으로 b의 존재를 말하는 것이며, a가 없다면 b의 존재는 의미가 없음)
- pointer의 사용은 다음과 같다.

ex) atof(char *); // char형의 변수를 역참조하는 pointer변수를 parameter로 함을 의미

int y, z[10];
int x = 1;
int *ip;  //pointer변수의 선언, ip의 역참조가 int의 형태가 되어야 한다는 의미이다.
ip = &x; //ip에 int형의 변수값을 갖는 x의 주소가 할당됨
*ip = 0; //ip의 역참조 즉, x의 값을 0으로 함
z = *ip; //ip의 역참조 즉, z = x와 동일하므로, z의 값은 0이 됨
ip = &z[0]; // ip에는 int형 변수값을 갖는 z[0]의 주소가 할당됨
*ip = *ip +10; // 이것은, z[0] = z[0]+10을 의미함

- 단항연산자 &, *은 arithmetic operator보다 더 tight하게 묶여 있다. 
ex) int *ip, *iq x; 
ip = &x;
y = *ip + 1; // y = x + 1 과 동일함
*ip += 1; // x += 1 과 동일함
++*ip // ++x 와 동일함
*ip++ // *(ip++) 와 동일함 => 괄호의 사용에 주의!
(*ip)++ // x++ 과 동일함
iq = ip // ip또한 variable이므로, iq에 주소값을 할당할 수 있음.

5.2 Pointers and Function Arguments

- function의 argument는 value값이 복사되어 들어가기 때문에, function내부에서 변경은 바깥에 적용되지 않음 
하지만, argument로 pointer를 사용하면 dereferencing을 통해, function내부에서 값의 변경이 가능함

5.3 Pointers and Arrays

- pointer와 array는 매우 강한 연관관계를 가지고 있음
- array name 자체는 array의 첫번째 element 주소를 나타내는 pointer와 동일함
ex) &a[0] == a // True
- pointer에 i(정수)를 더한 것은 pointer의 다음 object 주소를 나타내는 것임
이것을, array에 적용하면 다음/이전 i번째 element를 가리게 됨(그것이 존재할 경우에만 가능)
ex1) (pa = a+3) == &a[3] // True
ex2) pa = &a[2]
pa[2] == a[4] //True
*(pa-1) == *(a+1) // True  
*(pa-4) // 존재하지 않으므로 불가능
- pointer가 array를 가리킬 경우, p[i]로서 다음을 표현할 수 있음
ex) p = &a[1]
p[1] == a[2] // True
- 특별히, array name은 pointer임에도 불구하고, 다른 pointer값을 할당하거나 increment(++/--)(다음/이전 object를 가리키도록함)를 할 수 없음
하지만, array가 function의 argument로 들어갈 경우, array가 아닌 pointer로 들어가게 되므로, ++나 다른 pointer값으로 할당이 가능함
ex) int a[]
a = p //불가능
a++ //불가능

5.4 Address Arithmetic

- pointer의 initialization은 0 또는 address를 포함하는 이전에 정의된 표현으로만 가능하다.

- valid한 연산은 다음과 같다.

- 같은 type의 pointer의 할당
- array pointer와 integer의 덧셈/뺄셈
- array pointer간의 덧셈/뺄셈
- 0 (NULL) 과의 비교/할당 

- pointer가 실제로 가지는 주소값으로 그 외의 float 연산을 하거나, 곱셉/나눗셈/shift 연산을 하는것은 적절하지 않음
- pointer는 예외적으로 0 (또는 symbolic constant NULL)이라는 integer값을 가질 수 있는데, 이것은 유효한 주소가 아님을 나타낸다.

5.5 Character Pointers and Functions

- char a[] = "string1" 과
  char *b = "string2" 의 차이점은, a는 array이고, b는 array를 가리키는 pointer라는 점이다.
- pointer를 쓸 경우, string내의 position을 나타내는 제어변수 i, j 등을 사용하여 반복문을 제어하지 않고, compact하게 코드를 구성할 수 있다.
또한, 문장의 끝은 항상 '\0'인데 이를 이용한 제어에서 예를 들자면,
while(*s != '\0') 는 while(*s)와 같다. 이러한 사용은, 개념적으로 매우 편리하다.

5.6 Pointer Arrays; Pointers to Pointers

- Pointer또한 variable이기 때문에, array의 element로 사용할 수 있다. 
- 이러한, pointer를 element로 갖는 array는 다음과 같이 선언할 수 있다.
ex) char *a[]
여기서, a는 pointer형태의 첫번째 element의 주소를 가리키는 pointer가 된다.(pointer to pointer)
- 이러한 구조는, 여러 character나 number 집합들(배열들)을 control할 수 있게 한다.
- 예를 들어, 문자열의 정렬시 문자열의 실제 위치를 바꾸어 정렬시키지 않고.
 pointer array를 이용하여 pointer array내부 순서만 바꾸어 주는 식으로 정렬하면 overhead를 줄일 수 있다.

5.7 Multi-dimensional Arrays

- 2차원 배열
- 실질적으로 pointer array보다는 훨씬 덜 사용됨, 하지만, row순서대로 메모리상에서 연속되도록 배열이 저장되므로 접근이 빠름 
ex) char a[2][5] = {
{0, 1, 2, 3, 4}
{6, 7, 8, 9, 10}
}
- element를 array로 하는 array, a[0][1]이 첫번째 행의 첫번째 열 원소를 가리킴
- 함수의 argument로 전달할 경우, 반드시 column의 갯수를 명시하여야 함. row의 갯수에 대해서는 free함
ex) f(int a[2][5]) 또는 f(int a[][13]) 또는 f(int (*a)[13]), 만약 f(int *a[13])으로 쓸 경우, 이것은 13개의 integer pointer를 가지는 것을 전달한다는 뜻이 됨

5.8 Initialization of Pointer Arrays

- pointer array의 initialization은 다음과 같이 수행된다. element의 숫자를 굳이 써주지 않아도 컴파일러가 그 부분을 계산해준다.
- ex) char *month[] = {
"Illegal month",
"January,", "February", "March",
"April"
}
- pointer array의 element는 각 string을 가리킨다.

5.9 Pointers vs. Multi-dimensional Arrays

- Pointer array는 pointer가 가리키는 각 array가 길이가 서로 달라도 상관없지만,  Multi-dimensional array에서 각 row의 array의 길이는 모두 같아야 한다. 
- Multi-dimensional array는 row순서대로 array가 연결되어있고, 동일하게 고정된 array의 길이를 사용하기 때문에 
그것보다 작은 길이로 초기화할 경우, 메모리 공간의 단편화가 발생한다.

5.10 Command-line Arguments

- 프로그램을 실행할 때, command line을 통해서 parameter을 전달 할 수 있다. 이 때, main함수는 두가지 argument를 호출하는 방식을 취한다.
하나는 argument의 숫자를 나타내는 'argc'이고, 다른 하나는 argument 문자를 가리키는 포인터를 element로하는 pointer array인 'argv'이다.

ex) echo hello world 라는 command를 입력했다면, echo는 프로그램이름이며, argc = 3, argv에는 argv[0],argv[1],argv[2]순으로 'echo', 'hello', 'world' 가 들어가게 된다.

- argv[0]은 프로그램 호출 이름이며, 따라서 parameter은 argv[1]부터 시작하게 된다.

5.11 Pointers to Functions

- Function은 variable이 아니지만, pointer는 function의 address를 가리킬 수 있음
- Function의 argument로 pointer to function을 집어넣을 수 있음, 이것은 조건별로 다른 내부 함수를 사용하고 싶을 때 사용함
ex) qsort(int(*)(void *, void *)){
...
}
=> qsort 함수는 argument로 함수의 pointer를 받고 있음, pointer가 가리키는 함수는 으로 int형을 반환함
void*는 pointer를 argument로 가질 경우에만 쓰이며, 이것에는 어떠한 type의 pointer든 casting될 수 있음(하지만, 명시적으로 casting을 표현하는 것이 좋음)
하지만, void형의 pointer를 다른 type으로 casting할 경우, 반드시 명시적으로 void타입으로 형변환을 해주어야 함

5.12 Complicated Declarations

- C언어의 선언의 문법은 매우 복잡함, 이것은 왼쪽에서 오른쪽 순으로 선언이 읽혀지지 않는데에 문제가 있음
- 따라서, Declaration -> Word Description 으로 변환해 줌으로서 문법을 분석할 수 있고, 이 역할을 하는 것이 dcl 함수임
- 반대로, Word Dexciption -> Declaration도 가능함(undcl)

- 올바르게 정의된 선언은 dcl이며, 그것은 아래의 정의를 이용하여 recursive하게 구문분석할 수 있음
- dcl : optional *'s direct-dcl
- direct-dcl : name
(dcl)
direct-dcl()
direct-dcl[optional size]


ex) int (*pf)();

pf는 name이므로 direct-dcl
*pf는 *direct-dcl 이므로, dcl // pf is pointer
(*pf)는 (dcl) 이므로, direct-dcl 
(*pf)()는 direct-dcl() 이므로 direct-dcl //pf is pointer to function  
따라서, 올바르게 정의됨 

'프로그래밍 > C language' 카테고리의 다른 글

7. Input and Output  (0) 2021.08.19
6. Structures  (0) 2021.08.14
4. Function and Program Structure  (0) 2021.03.29
3. Control Flow  (0) 2021.03.29
About C language bulletin board  (0) 2021.03.29