Major S-T-U-D-Y/System Programming

9. Derived type - array, pointer, and structure (1)

rlo-lo 2024. 11. 12. 15:03

C data type

c data type 은  basic, derived, enumerated type으로 나뉜다. 여기서는 basic 과 derived 타입만 다루기로 한다. 

basic type  : C에서 가장 기본이 되는 데이터 타입이다 ex ) int, float, char, void .. 

- primitive data type, built in data type 이라고도 한다. 

 

Derived type : 기본 데이터 타입을 받은 데이터의 집합이나 주소 등을 가르키는 타입니다. ex) array, structure, union, pointer... 

 

 

Derived types

* pointer to... 
[] array of ... 
() function returning

 

복잡하게 선언된 derived type을 해석하기 위해  clockwise / spiral rule 의 선언 방식을 이해해보자. 

1. 식별자( 변수, 함수 이름) 에서부터 시작한다. 

2. 내부에서 외부로 이동한다. 오른쪽부터 시계방향으로 !

 우선 순위 : [] , (), >> * 

 * 의 역할은 두 가지 경우가 있다. 하나는 포인터 타입을 나타낼 때, 하나는 operator로써 역참조할 때)

char * foo[3] // foo is an array of pointers to char
char (* foo) [3]  // foo is a pointer of array of char

https://lear.microsoft.com/ko-kr/cpp/cpp/cpp-built-in-operators-precedence-and-associativity?view=msvc-170

연산자 우선순위는 단항 > 산술 > 관계 > 논리 > 대입 연산자 순이다.  하지만 모든 연산자 우선순위를 암기할 수는 없으니까,,,

 

→ [] () 이 세가지가 가장 높은 우선순위를 가진다 / 단항연산자 + - * 이 이항연산자보다 높은 우선순위를 가진다는 것만 알고 넘어가자!! 

 

Function pointers 

- 선언, 배열 위치 저장, 함수,,, 

- pointer to a function : declaration 

Returning-type (*fptr) (parameter-type list);



int add(int a, int b) {...}; int mul (int a, int b) {...}; 

// 1. pointer to function that returns int  생성하고, 2개의 parameter 
int (*f) (int , int);   - 8 byte 

// 2. 주어진 함수를 포인터에 할당한다. 
f = add; 

// 3. 함수 포인터를 통해 함수를 호출한다 
int ans = (* f) (4,5);

 

 

 

Type Expressions puzzele 

예시를 통해 알아보자. 해석 실수를 주의할 것!! 

int p ; // p is integer
int p[7]; // p is array[7] of integer
int * p ;// p is pointer to integer 
int * p[7] ;// p is array[7] of pointer  to integer 
int (*p) [7] ; // p is pointer to array[7] of interger 
int ** p ; // p is pointer to pointer to integer 


void f(); // f is function returning void 
void * f() ; //f is function returning pointer to void 
void (*fp) (); // fp is pointer to function returning void 
void * (*fp) () ; // fp is pointer to function returning pointer to void 
void ( *fp[7]) () ; // fp is array[7] of pointer to function returning void

 

 

gcc 의 sizeof  옵션을 사용하면 해당 함수의 할당된 size를 알 수 있는데 , int f(int, int) 처럼 body 가 구현되지 않은 경우는 매우 작은 크기로 저장되며, 1바이트로 표시된다. 구현은 하지 않았지만 선언은 되었으니 당연하게도 심볼 테이블에 엔트리가 형성될 수 있고, 함수의 주소를 참조할 수도 있다. 

 

const key 

1. const int * p // p is pointer to a int constant // 수정불가 

2 .int * const p // p is constant pointer to int 

Q. const 위치에 따른 차이는?

1의 경우 포인터 자체가 가르키는 위치를 변경할 수 있으나, 기존 포인터가 가르키는 장소의 content는 변경할 수 없다.

2의 경우 포인터 자체가 가르키는 위치를 변경할 수 없고, 기존 포인터가 가르키는 장소의 content(int value)는 변경할 수 있다. 

 

 

Array 

T A[N] ; // array of data type T and length N  N개의 타입이 모두 T
N* sizeof(T) = N * K // K만큼 건너뜀으로써 index control이 가능하다 !!! 
type of A : T * // 식별자 A는 constant address of array 를 나타낸다.
// 여기서 A는 배열 이름이면서 시작주소이기도 함. 즉, 배열의 주소를 가리키는 포인터!

 

* A 는 A[0] 과 같다 → machine level 에서  array index 에 의한 접근은 pointer에 의해서도 가능하다 

ex) e[i] → movl ( %rdx, %rcx, 4), % eax //rdx는 e의 주소, i는 인덱스 , 4는 type sixe 

 

Two-Demensional (nested) arrays

- 선형의 메모리에 저장됨  a[3][4] 라면 array[3] 이 4개 선형으로 위치함

 

Row acess code

int * fun (int index) 
{ return fun[index[; 
}



int fun[4][5];
# %rdi  = index 
leaq (%rdi, %rdi, 4), %rax # 5index
leaq fun(, %rax, 4) , %rax # fun + 20index

 

A + I * (C * K) ( + J * K) .// K는 배열 한 칸 내부 type 

 

Multi-level array 

int type array[5] 3개 각각 선언 

int * univ[3] = { uw, cmu, ucb} ; //24비트, 3개의 공간에 각각의 array 주소를 담고 있음

 

- multi level에서는 메모리 접근이 2번 이뤄진다. 1. 시작주소 row array 접근  2. array 내에서 실제 content 접근 

- 동적 데이터로 구성됨으로써 할당 공간은 작지만, 시간이 오래걸린다... 

mem [mem[univ + 8* i ] + 4(j) * digit]