728x90
CSAPP
3.9 이기종 (Heterogeneous) 자료구조
- C는 서로 다른 유형의 객체를 연결해서 자료형을 만드는 두 가지 방법을 제공한다. Struct 키워드를 사용해서 선언하는 구조체는 다수의 객체를 하나의 단위로 연결한다. 키워드 union으로 선언하는 공용체는 하나의 객체를 여러개의 다른 자료형으로 참조 될 수 있도록 한다.
3.9.1 구조체
- C struct 선언은 서로 다른 유형의 객체들을 하나의 객체로 묶어주는 자료구조를 생성한다. 하나의 구조체 내의 서로 다른 컴포넌트들은 이름을 이용해서 참조된다. 구조체의 구현은 구조체의 모든 컴포넌트들이 메모리의 연속된 영역에 저장되며, 구조체의 포인터가 첫번째 바이트의 주소라는 점에서 배열과 유사하다. 컴파일러는 각 필드의 바이트 오프셋을 가리키는 각 구조체 유형에 관한 정보를 관리한다. 컴파일러는 메모리 참조 인스트럭션에서의 변위로 이 오프셋을 사용하여 구조체 원소 참조를 생성한다.
- 기계어 코드는 필드 선언이나 이르멩 관한 정보를 포함하지 않는다.
3.9.2 공용체
- 공용체 union는 C언어의 자료형 체제를 회피해서 하나의 객체가 다수의 자료형에 따라 참조될 수 있도록 해준다. 공용체를 선언하는 문법은 구조체와 동일하나 그 의미는 매우 다르다. 다른 필드들이 메모리의 다른 블록을 참조하는 것이 아니라 동일한 블록을 참조한다.
- 공용체의 전체 크기는 유용할 수 있지만, C언어의 자료형 체제에서 제공하는 안전망을 피해가기 때문에 오히려 치명적인 버그를 발생 시킬 수도 있다. 한가지 응용은 어떤 자료구조의 서로 다른 두 개의 필드를 상호배타적으로 사용한다는 점을 미리 알고 있는 경우다.
- 이 경우 구조체보다는 공용체로 이 두개의 필드를 선언하면 전체 할당된 공간을 줄일 수 있다.
- 일반적인 방법으로 공용체에서 다른 여러가지 선택을 정의하는 열거형(enumerated) 자료형을 사용하고, 태그 필드와 공용체를 포함하는 구조체를 만드는 것이다.
3.9.3 데이터의 정렬
- 많은 컴퓨터 시스템들은 기본 자료형들에 대해 사용 가능한 주소를 제한하고 있어서 어떤 객체의 주소는 어떤 값 k의 배수가 되도록 요구한다. 이러한 정렬 제한은 프로세서와 메모리 시스템간의 인터페이스를 구성하는 하드웨어 설계를 단순화 한다.
- 정렬은 자료형 내의 모든 객체들이 각각의 정렬 제한 사항을 만족하는 방법으로 조직되고 할당되도록 강요된다.
- 구조체가 관련된 코드에서 컴파일러는 구조체의 각 원소들이 각각의 정렬 요구사항을 만족하도록 필드 할 당시 빈 공간을 삽입한다. 그러면 구조체는 자신의 시작주소가 가져야하는 정렬요건이 정해진다.
- 컴파일러는 구조체의 마지막에 0을 채워 구조체 배열에서 각 원소가 각각의 정렬요건을 만족하도록 해준다.
3.10 기계수준 프로그램에서 제어와 데이터 결합
3.10.1 포인터 이해하기
- 포인터는 C프로그래밍 언어에서 핵심 특징이다. 이들은 다른 자료구조 내 원소들에 대한 참조를 생성하는 통일된 방법으로서의 역할을 수행한다.
- 포인터는 연관된 자료형을 갖는다. 이 자료형은 어떤 종류의 객체를 이 포인터가 가리키는가를 의미한다.
- int *ip;
- char **cpp;
- 변수 ip는 int형 객체로의 포인터지만, cpp는 자기 자신이 포인터인 객체를 가리키는 포인터이다. 일반적으로 객체가 자료형 T를 갖고 있다면, 포인터는 자료형 T를 갖는다. 특수한 void 형은 범용(generic) 포인터를 표시한다. 예로 malloc 함수는 범용 포인터를 리턴하며, 이것은 할당연산의 명시적 또는 암묵적 형변환(casting)을 통해서 자료형을 갖는 포인터로 변환된다.
- 모든 포인터는 특정값을 가진다. 이 값은 특정 자료형을 갖는 어떤 객체의 주소다. 특수 값인 NULL(0)은 포인터가 아무곳도 가리키지 않는 것을 의미한다.
- 포인터는 & 연산자를 사용해서 만든다. 이 연산자는 lvalue로 구분되는 C언어의 모든 수식에 적용될 수 있으며, lvalue는 할당문 좌측에 올 수 있는 식을 의미한다.
- 여기에는 변수, 구조체, 공용체, 배열의 원소들이 해당한다.
- 포인터는 *연산자를 사용해서 역참조한다. 그 결과 포인터와 연관된 자료형을 갖는 값을 가져온다. 역참조는 정해진 주소에 저장하거나 주소로 부터 값을 가져오는 등의 메모리 참조를 사용하여 구현한다.
- 배열과 포인터는 밀접한 관련이 있다. 배열의 이름은 마치 포인터 변수처럼 참조 될 수 있다.(그러나 변경될 수는 없다) 배열의 참조(a[3])은 포인터 연산이나 역참조와 동일한 효과를 갖는다. 배열 참조와 포인터연산은 객체의 크기에 따라 오프셋을 조절해야 한다.
- 포인터 P에 대한 식 p+i를 값 p를 사용해 작성할 때 최종주소는 p + L * i로 계산된다.
- 한 종류의 포인터에서 다른 종류로의 자료형 변환은 그 종류만 바뀔뿐 값은 변화가 없다. 형변환의 한가지 효과는 포인터 연산의 크기 변환을 변경하는 것이다. 만일 p가 값 p를 갖는 자료형 char* 의 포인터라면 (int*)p+n은 p+28을 계산하며 (int*)(p+7)은 p+n을 계산한다. (형변환이 덧셈보다 우선순의를 갖는다.)
- 포인터는 함수를 가리킬 수도 있다. 이것은 프로그램의 다른 부분에서 호출할 수 있는 코드에 대한 참조를 저장하거나 넘겨 줄 수 있는 강력한 기능을 제공한다.
- 포인터는 연관된 자료형을 갖는다. 이 자료형은 어떤 종류의 객체를 이 포인터가 가리키는가를 의미한다.
728x90
'Study > TIL(Today I Learned)' 카테고리의 다른 글
24.01.26 CSAPP 3.10.3 - 3.10.5, LCS, Knapsack (1) | 2024.01.26 |
---|---|
24.01.25 시험,CSAPP 3.10.2 , Algorithm,코어타임 (1) | 2024.01.26 |
24.01.23 CSAPP 3.8, 복습,2Week, Python (1) | 2024.01.24 |
24.01.22 CSAPP 3.6.5 - 3.7, 복습 (0) | 2024.01.23 |
24.01.21 백준 1191,5639,1197,2606,1260 (2) | 2024.01.21 |