# [프로그래밍 언어] 3. Data Type

## 서론 Introduction

---

### 데이터 타입

- **데이터 값들의 모임**과 그들 값들에 대한 미리 정의된 **연산들의 집합**

- **사용자-정의 타입 user-defined type**: C언어에서 `typedef`를 사용하여 없는 타입 정의

    - 의미 있는 이름을 사용하여 향사된 판독성 제공

    - 프로그램 수정에 도움 제공

- **추상 데이터 타입 abstract**: 사용자-정의 타입에서 발전, 최근 대부분의 언어에서 지원

- **객체 object**: 사용자-정의 추상 데이터 타입의 **인스턴스 instance**

- **기본 데이터 타입**: 다른 데이터 타입을 이용하여 정의하지 않은 데이터 타입

    - 거의 모든 프로그래밍 언어가 기본 데이터 타입 집합을 제공

    - 어떤 기본 데이터 타입은 하드웨어의 반영

## 기본 데이터 타입 Primitive Data Types

---

### 수치 타입 numeric type

**정수 integer**

- 가장 공통된 기본 수치 데이터 타입

- **Java**: 4가지 크기의 부호 정수 제공 →  **byte, short, int, long**

- **C, C++**: **비부호** 정수도 제공

- **Python**: 하드웨어에 의해 직접 지원되지 않는 정수 타입 제공

    - 명시적 힙 동적 변수로 배열을 계속 키워나간다

    - 긴 정수 타입 long interger type → **제한되지 않는 길이**를 가질 수 있음

    - Overflow가 발생하지 않는다

**부동-소수점 수 floating-point**

- 실수를 모델링

- 대부분의 실수 값에 대한 근사값을 제공 → 표현 가능한 정수/실수의 개수는 유한함

- 대부분의 언어는 float, double을 제공

**복소수 complex**

- 일부 프로그래밍 어어들만 복소수 데이터 타입을 지원

- 주로 과학 분야에서 사용된다

- Python: 복숫 리터럴의 허수 부분은 j나 J로 끝남 → scipy

**십진수 decimal**

- 사무 시스템 응용 분야 지원하기 위한 프로그래밍 언어들에서 십진수 지원

- 대표적 언어들: COBOL, C# 등

### 불리안 타입 boolean type

- 모든 타입들 중에서 가장 단순: true, false

- 1950년 이후 설계뙨 대부분의 범용 언어에 포함됨

- C언어

    - C89는 불리안 타입을 지원하지 않고 0을 거짓, 0이 아닌 모든 값을 참으로 처리

    - C99와 C++은 불리안 타입을 지원, 수치식 처럼 제공

- Java, C#: 부리안 식으로 사용하는 것을 허용하지 않는다

### 문자 타입 character type

- 문자 데이터는 수치 코딩으로 컴퓨터에 저장

- **ASCII**: 가장 공통적으로 사용하는 **8비트** 코딩 기법 (실제로는 **7비트 + start bit**)

- **Unicode**: 16비트 문자 코드로 세상에 존재하는 대부분의 자연어 문자 표현 가능

    - Java는 Unicode를 쓰고 모든 문자 처리 가능 → 백엔드에서 사용

- **USC-4, UTF-32**: 4바이트 문자 코드

- 대부분의 프로그래밍 언어가 **문자**를 기본 데이터 타입으로 지원

- **Python**은 단일 문자를 단지 길이가 1인 **문자 스트링**으로 지원 (`’a’` == `“a”`)

## 문자 스트링 타입 Character String Types

---

### 스트링과 연산

- 가장 공통된 스트링 연산: 배정, 접합, 부분 스트링 참조, 비교, 패턴 매칭

**배정 assignment**

- 일련의 문자열을 다른 곳에 배정(다른 객체), 별칭을 제공 (같은 객체)

- 다른 곳에 배정할 경우 내용을 수정해도 원본은 변경되지 않음

**접합 catenation**

- b를 a에 접합시키는가, 새로운 영역에 접합시키는 것인가?

- 새로운 영역에 접합시키는 경우 별칭이 있을 때 별칭은 늘어나지 않는다

**부분 스트링 참조 substring reference** 

- 주어진 스트링의 부분 스트링에 대한 참조 → 배열의 **슬라이스(slice)**

**C언어**

- 스트링이 기본 타입으로 정의되지 않음

- 스트링은 **단일 문자들의 배열**로 저장 → 스트링의 끝을 **널 NULL 문자**로 처리

- 스트링 연산은 표준 라이브러리 함수로 제공: `strcpy()`, `strcat()`, `strlen()`

    - `strcpy(dest, src)`: 스트링이 오버플로하는 것에 대해 보호하지 않음

    - src의 길이가 dest보다 크다면 dest 다음 30바이트를 덮어쓰게 됨

**Java**

- String, StringBuffer 클래스에 의해서 지원

    - **String**: 값의 **변경이 불가**능한 상수 스트링

    - **String Buffer:** 값이 **변경 가능**한, 단일 문자들의 배열과 유사

**Python**

- 스트링이 기본 타입

- 스트링은 변경 불가, Java의 String 클래스와 유사

- 문자와 부분 스트링 참조에 대해서는 문자들의 배열과 매우 유사

**스트링 길이 선택 사항**

- 스트링 길이에 따라 선택 사항들이 존재한다

- 정적 길이 스트링, 제한된 동적 길이 스트링, 동적 길이 스트링

### **정적 길이 스트링 static length string**

- 길이는 정적, 스트링이 생성될 때 설정 됨

- Python의 스트링, Java의 String 클래스

**구현**

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/204645_8985vLNSaGcKDG4dhE?q=80&s=1280x180&t=outside&f=webp)

- **서술자 descriptor**는 단지 **컴파일 과정**에서만 요구

- 서술자는 세 가지 필드를 가짐: **타입의 이름, 길이, 주소**

    - 실행 시점에서 메모리가 할당된 후에는 필요 없다 (서술자 = symbol table)

### **제한된 동적 길이 스트링 limited dynamic length string**

- 스트링이 그 변수 정의에서 선언, 고정된 최대 길이까지의 가변적인 길이를 갖는 것을 허용

- C의 스트링 (문자들의 배열, 마지막 글자는 null)

**구현**

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/204710_q9E3gV3qszwNpEhY16?q=80&s=1280x180&t=outside&f=webp)

- 고정된 최대 길이와 현재 길이를 저장하는 **실행-시간 서술자**를 요구

- 대부분의 경우 서술자들은 **심볼 테이블**에 저장

    - 컴파일러는 current length를 알 수 없다 → symbol table을 남겨 interpreter처럼 동작

- C와 C++: 스트링의 끝이 널 문자로 표시 → 실행-시간 서술자를 요구하지 않음

    - C에서는 current length를 사용하지 않기 위해 NULL을 사용

    - 배열의 색인 값에 대해 범위 검사 X → 최대 길이도 사용하지 않음

    - maximum length를 사용하지 않기 위해 오버플로우 검사 X → 보안상 문제 발생

- 특별히 동적 기억공간 할당을 요구하지 않음 → 한 번의 할당 과정만 필요

### **동적 길이 스트링 dynamic length string**

- 최대 길이 제한 없이 가변 길이를 갖는 것을 허용

- Java의 StringBuffer 클래스, JavaScript, Perl, 표준 C++ 라이브러리

**구현**

- 더 복잡한 기억 공간 관리를 요구

- 스트링의 길이와 바인딩되는 기억공간은 동적으로 늘어나거나 줄어들어야 함

**동적 할당과 반환을 지원하는 방법**

- 스트림을 **연결 리스트**에 저장

    - 스트링이 늘어날 떄 새롭게 요구된 메모리 셀은 **힙**의 어느 곳으로부터 올 수 있음

    - 단점: 연결 리스트의 링크를 표현하기 위해 여분의 메모리 필요, 스트링 연산의 복잡성

- 스트링을 힙에 할당된 개개의 문자들을 가리키는 **포인터의 배열**로서 저장

    - 장점: 여분의 메모리를 사용하지만 연결리스트 접근보다 더 빠를 수 있음

- 스트링 전체를 **인접한 기억공간 셀**들에 저장

    - 단점: 스트링이 늘어날 때 문제 발생

        - 기존의 셀들에 인접한 기억공간에 여유가 없을 때

        - 새로운 메모리 영역을 찾고 스트링 이전 부분을 새로운 영역으로 이동

        - 이전 스트링에 대해서 사용된 메모리 셀 회수

## 열거 타입 Enumeration Types

---

- 이름 상수들인 모든 가능한 값들이 그 정의에서 제공되는, 즉 열거 타입

- 열거 상수라 불리는 이름 상수들의 모임을 정의 ,그루핑 하는 방법을 제공

-   → 사용할 문자열이 한정되어 있다면 열거 타입을 사용

- Python, JavaScript, Perl, PHP, Ruby, Lua 등 최근 개발된 스크립트 언어들은 지원하지 않음

**C언어**

```javascript
enum colors (red, blue, green, yellow, black); // 열거형 타입 정의
colors myColor = blue, yourColored;            // 열거형 변수 정의
```

- colors 타입은 열거 상수에 대해서 디폴트 내부 값 0, 1, …을 사용

- 이 열거 값들은 정수 문맥에서 사용될 때 int로 강제 변환 
- → 실제 값의 의미를 알 수 없고 범위를 벗어나는 문제가 발생할 수 있음

**Java**

- 열거 타입은 클래스라는 것을 제외하고는 C와 유사

- **신뢰성** 측면에서 차이가 존재

    - 어떤 **산술 연산도 여러 타입에 적용되지 않음**

    - **범위 밖**의 값을 **할당 받을 수 없음**

- 열거형은 이름을 갖는 값들은 쉽게 인식되기 때문에 **판독성**이 매우 향상된다

## 배열 타입 Array Types

---

### 배열

| **배열** | **구조체** |
| --- | --- |
| 동질적인 데이터 원소들의 집합체 (데이터 원소들은 동일한 타입) | 서로 다른 데이터 원소들의 집합체 (데이터 원소들은 동일 / 다른 타입) |
| 배열의 이름은 포인터 → 배열을 넘기면 배열/pointer로 받음 | 구조체 이름은 구조체 → 구조체를 넘기면 구조체로 받음 |

```javascript
int a[10];
struct A{
    int a;
    char c;
}
```

```javascript
[10, "abc", 7.5]
a = 10
a = 'abc'
a = 7.5

```

**C, Java, C++, Ada, C#**

- 배열의 모든 원소들은 **동일한 타입**에 속해야한다

- **포인터**나 **참조들**은 **단일 타입**을 가리키거나 **참조**하도록 제한

- 가리켜지거나 참조되고 있는 객체나 데이터값들도 단일 타입에 속함

**Python, JavaScript, Ruby**

- 변수들은 객체나 데이터 값들에 대한 **타입과 상관 없는 typeless 참조**들

- **배열**은 여전히 **단일 타입의 원소들로 구성**되지만, 그 원소들은 **다른 타입 객체 또는 데이터 값들을 참조** 가능

- 배열의 원소들이 **동일한 타입**에 속하기 때문에, **원소들은 여전히 동질적**임

### **색인**

- 배열은 **두 레벨의 구문 메커니즘**으로 참조됨

    - 집단체 이름 aggregate name

    - 첨자 subscript 또는 색인 index

- 개개의 원소는 집단체 첫 번째 원소와의 상대적인 위치로 식별됨 → 시작주소로부터 얼마나 떨어져 있는가?

- 배열 원소들의 참조는 첨자나 색인으로 나타냄

**유한 사상 finite mapping**

- 선택 연산은 **배열 이름과 첨자 값**들의 집합으로부터 집단체의 한 원소를 **사상 mapping**으로 생각됨

- 배열은 떄때로 **유한 사상 finite mapping**이라고 불림

- 기호로 표시하면 다음과 같음: `배열_이름 (첨자_값_리스트) → 원소`

**첨자의 범위 오류**

- 여러 프로그램에서 발생하는 공통된 현상

- 범위 검사를 요구하는 것은 언어의 신뢰성에 중요한 요소

- Java, ML, C#은 범위 검사를 명세

- C언어를 포함한 많은 프로그래밍 언어들은 첨자에 대한 검사를 명세하지 않음

### **첨자 바인딩 subscript binding과 배열 유형**

- 배열 변수에 대한 **첨자 타입의 바인딩**은 보통 **정적**, 그 **첨자 값 범위**는 때때로 **동적**으로 바인딩

- C언어를 포함하여, 어떤 언어들에서는 첨자 범위의 하한이 묵시적으로 존재

    - C언어나 Java에서 모든 색인 범위의 하한은 0으로 고정

    - Fortran 98+는 색인 범위의 하한의 디폴트 값이 1

- 다른 언어에서 첨자 범위가 프로그래머에 의해 명세 되어야 함

- 배열은 3가지 기준으로 4가지 유형으로 구분 가능

    - **첨자 값 범위**에 대한 바인딩 → 첨자 값 범위

    - **기억 공간**에 대한 바인딩 → 정적, 동적

    - **기억공간의 할당 위치**에 기반하여 분류 → DS, heap, stack

**정적 배열**

- **첨자 범위가 정적**으로 바인딩 + **기억공간 할당이 정적**인 배열

- 장점: **실행 시간의 효율성**

    - 동적 할당이나 회수가 요구되지 않음

    - Data Segment에 있으면 메모리 접근에 직접 접근이 가능

- 단점: 배열에 대한 기억공간이 프로그램 실행 시간 전체에 걸쳐서 고정

    - Data segment 내부에 큰 공간을 잡고 프로그램이 끝날 때까지 사용한다면 비효율적

```javascript
int a[10];
f(){
    static int a[10]; // C언어에서 static으로 선언되는 배열은 정적 배열
}
```

**고정 스택-동적 배열**

- 첨자 범위가 정적으로 바인딩 + 기억공간의 할당이 실행 시간 중

- 선언된 기억 공간을 바인딩하는 시간에 이루어지는 배열

- 장점: 정적 배열에 비하여, **기억 공간의 효율성**이 존재

- 단점: 할당과 회수에 소요되는 실행 시간

    - 할당과 회수가 실행시간이 더 많이 든다 → 메모리를 할당하는 회수할 때 비용이 든다

```javascript
f(){
    int a[10]; // C언어에서 함수에 선언된 배열
}
```

**고정 힙-동적 배열**

- **첨자 범위와 기억공간**의 바인딩이 **기억공간이 할당된 후에 고정**

    - 고정 스택-동적 배열과 유사

    - 첨자 범위와 기억공간의 바인딩이 실행 중에 사용자 프로그램의 요청으로 이루어짐

    - 기억공간이 스택이 아닌 **힙으로부터 할당**됨

- 장점: **유연성** → 배열의 크기는 항상 문제에 맞춤화됨

- 단점: **할당시간** → 스택보다 힙으로부터 할당 시간이 더 김

```javascript
f(){
    mt[] array={1, 2, 3, 4} // heap에 저장
}
```

- C언어에서 `malloc()`과 `free()`로 힙의 할당, 회수 실행 → C의 배열에 대해 사용 가능

- Java에서 비포괄적 배열 (non-generic arrays = 타입이 지정된 배열)은 고정 힙-동적 배열

- 이 배열은 한 번 생성되면, 동일한 첨자 범위와 기억공간을 유지함

**힙-동적 배열**

- **첨자 범위**의 바인딩과 **기억공간**의 할당이 **동적**, **배열의 존속기간** 동안 **여러 번 변**경 가능

- 장점: 다른 유형에 비해 **유연성**을 가짐 → 기억공간에 필요에 따라 늘거나 줄어들 수 있음

- 단점: **할당과 회수의 시간이 길어지고**, 프로그램 실행 중에 **여러 번 발생** 가능

```javascript
List<String> list = new ArrayList<String>();
list.add("홍길동");
STring name = list.get(0);
```

- Java에서 포괄적 클래스인 ArrayList로 만들어진 배열

- 첨자를 사용하지 않음

- `add()`, `get()` 메소드로 원소를 삽입하거나 가져오기도 함

- Python 배열은 원소를 추가하거나 다른 배열과의 접합하는 메소드를 통해 크기가 들어남, 한 원소나 슬라이스들을 삭제 가능

### 배열 연산

- 배열 단위로 연산을 수행하는 연산

- 공통된 배열 연산: 배정, 집합, 동등과 비동등을 위한 비교, 슬라이스

    - **배정**: 배열 하나를 통째로 다른 배열에 배정

    - **집합**: A, B를 접합하거나 새로 만들어서 접합 가능 ****

    - **동등과 비동등을 위한 비교**: 내용으로 비교, 참조로 비교

    - **슬라이스**: 배열의 부분 구조, 배열의 부분을 한 단위로 참조하기 위한 매커니즘

        - 파이썬에서 리스트를 슬라이스를 이용하여 표현 가능

- C언어는 배열 연산을 제공하지 않음 (라이브러리 함수로 제공)

- Java도 메소드를 통하는 경우를 제외하고는 배열 연산을 제공하지 않음

- Python의 배열 연산

    - 동적 배열의 모든 특성을 가지지만, 리스트 (List)라고 불림

    - 배열 원소는 객체에 대한 참조 (동질 원소) + 객체들은 임의의 타입 간으 (이질적인 값 참조 가능)

    - 참조 변경이기는 하지만, 배열 배정을 제공 (배정 연산 제공)

    - 배열 접합 연산 (`+`)과 원소 멤버십 연산 (`in`) 제공

    - 두 개의 비교 연산 (`is`)와 (`==`)를 제공 
    -   → `is`는 참조가 같은데, `==`는 내용이 같은지 검사

    - 슬라이스 연산(`[:]`)도 제공

### 직사각형 배열과 톱니형 배열

**직사각형 배열 rectangular array**

- 모든 행들이 동일 개수의 원소들을 포함

- 모든 열들이 동일 개수의 원소들을 포함

- Fortran, Ada, C#

**톱니형 배열 jagged array**

- 행들의 크기가 동일할 필요가 없는 다차원 배열

- 톱니형 배열으 다차원 배열이 실제로는 배열을 포함하는 배열일 떄 가능

- C, Java는 톱니형 배열 지원, but 직사각형 배열은 지원하지 않음

### 배열 타입의 구현

**배열의 발전 단계**

- 초기 배열에서의 주요 진보: 동적 배열, 슬라이스

- 최근의 주요 진보: 연상 배열 (연관 배열)

**배열 타입의 구현**

- 배열을 구현하는 것은 기본 타입 구현보다 더 많은 컴파일 노력이 요구됨

- 배열 원소의 접근을 허용하는 코드는 컴파일 시간에 생성되어야 함

- 생성된 코드는 실행 시간에 배열에서 특정 원소들의 주소를 계산할 수 있어야 함

**1차 배열**

```javascript
주소(list[k]) = 주소(list[하한]) + ((k - 하한) * 원소_크기)
```

- list[k]로 표현되는 일차원 배열의 접근 함수

**다차원 배열**

```javascript
주소(a[i, j]) = 주소(a[row_lb, col_lb]) + (((i - row_lb) * n) + (j - col_lb)) * 원소크기
```

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/210431_sV5cwYRgIgaIXsO8Jw?q=80&s=1280x180&t=outside&f=webp)

- 두개 이상의 차원을 갖는 데이터 타입의 값들은 1차원 메모리로 사상

- **행-우선 순서**: 첫 번째 행의 원소 먼저 저장 후 다음 행의 원소 저장 (대부분의 언어)

- **열-우선 순서**: 첫 번째 열의 원소 먼저 저장 후 다음 열의 원소 저장 (Fortran)

## 연상 배열 Associative Arrays

---

- 원소 개수와 동일한 개수의 값(**키 key**)들로 **인덱싱**되는 **순서를 갖지 않는** 데이터 원소 모임

- 배열에서는 색인을 저장할 필요가 없음 (색인의 규칙성) 
- → 연상 배열에서 사용자-정의 키들이 그 구조에 저장

- 각 원소는 항목들의 쌍 (키, 값)이 됨

- 원소들에 대한 탐색 → 배열보다 훨씬 좋음 (묵시적인 해시 연산이 매우 효율적)

- 리스트의 모든 원소들에 대해 오퍼레이션을 수행해야하면 배열이 더 효율적

**지원 언어**

- Python에서 지원 (딕셔너리 → 값들이 모두 객체에 대한 참조)

- Java에서 표준 클래스 라이브러리로 지원

- 기타 직접 지원 언어: Ruby, Perl, Lua

- 기타 표주 클래스 라이브러리로 지원되는 언어: C++, C#

## 레코드 타입 Record Types

---

- 개개의 원소들이 이름으로 식별 → 오프셋을 통해 접근되는 데이터 원소들의 집단체

- 대부분의 언어에서 필드 참조를 위해 도트 표기법을 사용

- C 언어, C++, C#: `struct` 데이터타입으로 지원

- Python, Ruby: 딕셔너리 또는 해시로 구현, 레코드 자체가 배열의 원소일 수 있음

- Java: 데이터 클래스로서 정의 → 레코드 필드로서 역할을 수행

## 튜플 타입 Tuple Types

---

- 레코드와 유사한 데이터 타입, 원소들이 명명되지 않는다는 차이점

**Python 튜플**

```javascript
myTyple = (3, 5.8, 'apple') # 레코드와 유사, 각 원소를 가리키는 이름이 없음
myTyple[1] # 색인이 0부터 시작, 두 번째 원소를 참조 -> 5.8
```

- 변경 불가 튜플 타입 제공

- list 함수를 사용하여 배열로 변환할 수 있음

- 배열을 함수의 매개변수로 전달해야 하지만, 그 함수가 배열의내용을 변경하지 못하도록 할 때 사용

## 리스트 타입 List Types

---

- 함수형 언어인 **LISP**에서 처음 사용

- 최근에 일부 명령형 언어에 도입

**Python 리스트**

```javascript
myList = [3, 5.8, "grape"] # 이름에 리스트 값을 할당하여 생성
x = myList[1]              # x에 5.8이 배정
del myList[1]              # 원소 삭제 가능

# 리스트 포괄 구문
[x * x for x n range(12) if x % 3 == 0] # [0, 9, 36, 81]
```

- 배열로서도 역할을 수행

- 파이썬 리스트는 변경 가능 (Python 문자열은 변경 불가, 튜플도 변경 불가)

- 리스트는 임의의 데이터 값이나 객체를 포함할 수 있음

## 공용체 타입 Union Types

---

- 변수가 프로그램 실행 중 다르 시기에 다른 타입의 값을 저장할 수 있는 타입

**C, C++ 공용체**

```javascript
union flexType{
    int intEl;
    float floatEl;
};

union flexType el1;
float x;
...
el1.intEl = 27;
x = el1.floatEl;
```

- el1은 4바이트 크기의 메모리

- 마지막 배정문은 타입 검사되지 않음

- 시스템이 el1의 현재 값의 현재 타입을 결정할 수 없기 때문

- 시스템은 27의 비트 표현을 float 변수 x에 배정
- → 값이 올바르게 배정되었는지 여부는 관심 없음

## 포인터 타입과 참조 타입 Pointer and Reference Types

---

### 포인터 타입

- 메모리 주소 + 특수값(nil)으로 구성되는 값들의 범위를 갖는 타입

    - `NULL`: 접근 가능한 주소가 아니다

    - `nil`: C언어 → 최근에 값이 없다

**포인터의 두 가지 사용 용도**

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/220308_cYhRoganLRtUd51g0h?q=80&s=1280x180&t=outside&f=webp)

- **간접 주소 지정 형태**

- 동적으로 할당되는 **힙**이라는 기억공간 영역의 한 위치를 접근하는 데 사용

    - 힙 동적 변수 (무명 변수): 포인터나 참조 타입 변수로만 참조 가능, `malloc()` `new` 사용

**힙-동적 변수**

- 힘으로부터 동적으로 할당하는 변수 → 변수들은 이들과 연관된 식별자를 갖지 않음

- **포인터**나 **참조-타입 변수**들에 의해서만 **참조** 가능

- 이름 없는 변수 = **무명 변수**

**포인터 연산**

- **배정 연산**: 포인터 변수의 값을 어떤 주소로 설정

- **역참조 연산**: 포인터 변수에 바이딩된 메모리 셀이 가리키는 메모리 셀에 포함된 값 참조

**포인터 문제**

```javascript
int *arrayPtr1;
int *arrayPtr2 = (int*) malloc(sizeof(int)*100);
arrayPtr1 = arrayPtr2;
free(arrayPtr2);
// 이제 arrayPtr1은 허상 포인터 -> 포인터가 가리키고 있는 힘 기억공간이 반환
```

- **허상 포인터**: 회수된 힙-동적 변수의 주소를 포함하는 포인터

```javascript
int *p1;
int p2;
p1 = (int *)malloc(sizeof(int)*100);
p1 = &p2;
// 이제 malloc()으로 할당받은 힘-동적 변수는 쓰레기가 됨
```

- **분실된 힙-동적 변수**: 더 이상 접근할 수 없는 할당된 힙-동적 변수

    - 쓰레기 garbage, 메모리 누수 memory leakage

**C언어**

```javascript
j = *ptr // 역참조 연산
(*p).age // '*'로 역참조 후, '.'으로 필드 참조
p->age   // '->'로 역참조와 필드참조를 한꺼번에 처리
malloc() // 힙 메모리 관리르 위한 명시적인 할당
void *   // 포괄 포인터 -> 타입의 포인터, 역참조 불허
```

### 참조 타입

- 포인터와 유사, 참조 변수는 메모리의 객체나 값을 참조

- 참조에 대한 산술 연산은 무의미

- Java 클래스 인스턴스들은 **묵시적으로 회수** → **허상 참조가 존재할 수 없음**

- Python의 **모든 변수는 참조 변수**임 → **묵시적으로 역참조**

**Java**

```javascript
String str1; // null(nil)로 설정
...
str1 = "This is a Java literal string";
```

### 포인터와 참조 타입 구현

**포인터와 참조의 표현**

- 인텔 마이크로프로세서 기반: 세그먼트 + 오프셋 (2개의 16비트 셀, 총 32비트)

**허상 포인터**

- 비석 접근 방법 → 널리 사용되는 어떤 언어도 사용하지 않음

- 잠금-키 접근 방법 제안

- 현재 제안된 것 중 가장 좋은 해결책으로 **“묵시적 회수” 방법**이 존재

    - 프로그래머를 거치지 않고 힙-동적 변수를 회수

    - 실행-시간 시스템이 묵시적으로 회수 → 허상 포인터 X

    - Java, LISP 등에서 사용

**힙 메모리 관리**

- **참조 계수기 방법의 회수 시점**: 회수가 점차적으로 이루어지며, 접근될 수 없는 셀들시 생성될 때 수행 → **조기 접근 방법**

    - 참조 계수기 감소 연산 → 0이면 쓰레기, 가용 리스트에 반환

    - 문제: 공간 부담, 실행 시간, 순환 연결 시 복잡

    - 장점: 응용 프로그램 지연 감소

- **표시-수집 방법의 회수 시점**: 가용 기억공간이 부족할 때만 회수가 실행 → **지연 접근 방법**

    - 쓰레기 누적 허용, 모든 셀 할당 → 쓰레기 모음 (여분의 지시자 가짐)

    - 문제: 너무 드물게 수행, 수행되면 많은 시간 소요 → 점차적 표시 수집

For the site tree, see the [root Markdown](https://slashpage.com/yerim-devnote.md).
