[타입 동등성]
: 사용자가 새로운 타입을 정의하는 걸 허용하는 언어에서, 타입 동등 여부를 결정하는 주요 기준 두가지가 있다.
: 구조적 동등성 / 이름 동등성
[구조적 동등성 기준(Structual equivalence)]
: 타입 정의에 대한 내용 기반으로 동등성을 판단하는 기준
: 즉, 구조체상 같은형태일때 동등하다고 판단한다.
: Algol 68, Modula-3, C, ML등 에서 사용하는 방법
: 직관적이지만, low-level 실행 지향적이다.
# 구조적 동등성 예제
type student = record name, address : string age : integer
type school = record name, address : string age : integer |
: name이 달라도 내부구조가 동일해 동일한 타입으로 취급한다 (위 student, school 동일한 타입취급) => 구조적 문제 발생 가능...
[이름 동등성 기준(Name equivalence)]
: 타입 정의가 발생한 맥락 기준으로 동등성을 판단
: 즉, 각 타입 정의할때마다 새로운 타입을 소개한다.
: Java, C#, Pascal, Ada 등에서 사용하는 방법
: 아무리 내부 구조가 동일하더라도 서로 다르게 두개의 타입을 선언한 시점에서 다른 타입으로 취급한다.
: 타입의 name이 동등성 판단의 기준.
[타입 동등성 기준에 따른 타입 동등성 판단 예시]
: 숙지해두기
type R1 = record a, b : integer end; |
: 위와 같은 타입이 있다. (Pascal)
# 타입 예시 1
type R2 = record a : integer; b : integer end; |
: 이와 같이 선언의 format만 다른 경우는 대부분 동일한 타입으로 판단한다.
# 타입 예시 2
type R3 = record b : integer; a : integer; end; |
: 이와 같이 선언의 순서가 다른 경우.
: ML에서는 동등하지 않다고 판단
: 대부분의 언어들은 동등하다고 판단
# 타입 예시 3
type str = array [1..10] of char; type str = array [0..9] of char; |
: 배열의 길이는 같지만 index값이 다른 경우
: 대부분의 언어들은 동등하지 않다고 판단
: 몇몇 Fortran, Ada같은 언어는 동등하다고 판단
[Name equivalence의 변형]
typedef old_type new_type; // C언어 |
: new_type이 old_type에 대해 alias 된다.
: 그럼 이 두 타입을 2개의 이름을 가진 같은 타입(구조적 동등성)으로 취급? 아니면 동일한 구조를 가지고 있는 서로다른 두개의 타입(이름 동등성)으로 취급?
1) Strict name equivalence (염격한 이름 동등성)
: 위와같은 방법으로 생성된 aliased type을 서로 다른 타입으로 취급하는 경우를 의미한다.
2) Loose name equivalence (느슨한 이름 동등성)
: 위와 같은 방법으로 생성된 aliased type를 서로 같은 타입으로 취급한다 (두개의 name을 가진)
# Ada : 두 두가지 방법중 어느 방법을 사용할지 프로그래머에게 맡긴다.
- subtype : 동등하게 취급하는 경우
- derived type : 다르게 취급하는 경우
[두가지 동등성 기준 대표적인 예시]**
type cell = .. -- whatever type alink = pointer to cell // alise type blink = alink // alise p, q = pointer to cell r : alink s : blink t : pointer to cell u : alink |
# 엄격한 name equivalence 기준
- p, q 는 동등한 타입
- r, u 는 동등한 타입
: 같은 타입 name을 이용해 생성한 것들만 동등하게 취급
# 느슨한 anme equivalence 기준
- 위의 동등한 거 에 추가로
- r, s, u 동등한 타입
: name 달라도 alise 관계이기에 동등한 취급, 단 t는 다르다! (같은거 참조해도.. 이어져야함)
# 구조적 동등함 기준
: 6개의 변수다 동일하다.
[타입 전환(Conversion)과 Cast]
: 정적 타이핑되는 언어에서 특정 타입의 값이 기대되는 많은 맥락들이 존재한다.
# 특정 값 기대 맥락 예시 1 - statement에서
a := expression // 두 변수의 타입이 같다고 생각할 수 있다, |
# 특정 값 기대 맥락 예시 2 - expression에서
a + b // 이하동 |
# 특정 값 기대 맥락 예시 3 - subroutine에서
foo(arg1, arg2, ..., argN) //인자들의 타입을 해당 subroutine의 선언시의 파라미터의 값과 동일할 것이라 생각한다. |
: 이러한 기대를 위해 만약에 기대되는 타입과 들어가는 타입이 다르면 type conversion을 명시해줘야하고, 이는 실행 시점에 실행된다.
[타입 conversion 명시 주요 케이스]
1. 타입이 구조적 동일함(Structurally equivalent)로 고려되지만, 언어가 이름 동일성(name equivalence)으로 고려되는 경우
: 그냥 쉽게 말해 구조는 같지만 이름이 다른 경우
: low-level에서 값에 대한 동일한 세트를 가진다
: 실행시점에 딱히 추가적으로 실행되지않고, 단순히 컴파일러가 눈감아 주면 문제 될 것이 없다.
2. 타입들이 서로다른 값들의 집합 가지지만, 교차 값이 같은 방식(부분집합)으로 나타날때. (대표적인경우)
: 현재 변수가 유효한 기대타입 범위안에 있는지 실행시점에 검사한다 (check 해주는 코드 삽입)
: 검사 실패시 -> dynamic semanitc error 발생
: 검사 성공시 : 기존 값 변동없이 사용할 수 있다.
# 케이스 2 예시
f(char) // char의 범위는 -128 ~ 127 f(230) // dynamic emantic error 발생 |
3. 타입이 서로다른 low-level 가지지만, 서로의 값들 사이에서 일부의 일치점을 정의하는 경우.
: 이 경우에는 다른 타입으로 넘어갈때 서로의 타입 크기가 중요하다.
1) 32비트 정수형 -> 실수형
: 작은 범위의 타입에서 큰 범위의 타입으로 넘어가는 경우
: 손실 없음
2) 실수형 -> 정수형
: 큰 범위 타입에서 작은 범위의 타입으로 넘어가는 경우
: 손실 발생, overflow 발생
3) 서로다른 길이의 정수형간 conversion
: 높은데 위치해있는 바이트를 버리던가 부호 확장(sign-extending)한다.
# 타입 conversion 주요 예시
n : 정수형1 r : 실수형 t : 1...100 정수 subrange c : 정수형2 ... t := n // 3-2) 경우. run-tine sementic check 필요 n := t // 3-1) 경우. 검사 X r := n // 2 경우. 실행 시점 conversion 필요 n := r // 2 경우. 실행시점 conversion과 check 필요 c := n // 1 경우.검사 필요 X |
# C에서의 타입 conversion
r = (float) n; n = (int) r; |
: 실행 시점 conversion 수행
: 타입 conversion을 명시해 준다.
[Nonconverting Type Casts]*
: 변수의 타입 변환을 변수의 format을 바꾸는 것이아니라, 기존 값 그대로 두고 사용하는 방법이다.
: 그래서 더 작은 범위의 타입으로 변환된후 다시 큰 범위 타입으로 변환되어도, 값의 손실이 발생하지 않는다.
: 하지만, 위험한 상황 감지 어려워 진다
: 그래서 타입 시스템이 강한 언어에서는, 코드내 위험한 부분에 대해 적어도 label을 붙여, 문제 발생시 디버깅 수행한다.
# C++에서의 casting
: 기본적으로 C의 방식을 사용하는데, 추가로 더욱 안정적인 대안을 제공한다.
1) static_cast : 타입 conversion 수행. 기존 방식
2) reinterpret_cast : nonconverting type cast 수행
3) dynamic_cast : 다형성 타입의 포인터 방식 사용 (정적으로 유효성 보장 X, 동적으로 검사(checking))
A* a = (A*) p // static_cast 같은 경우는 강제로 p를 A* 타입으로 형변환하는데, 이때 p가 A*대입 불가능시 문제가 발생한다. // dynamic_cast가 이런 문제를 해결한다. |
'[프로그래밍 언어론]' 카테고리의 다른 글
프로그래밍 언어론 7-2-3강. 타입 추론(Type Inference) (0) | 2019.12.14 |
---|---|
프로그래밍 언어론 7-2-2강. 타입 호환성(Type Compatibility) (0) | 2019.12.13 |
프로그래밍 언어론 7-2강. 타입 검사(Type Checking) (0) | 2019.12.13 |
프로그래밍 언어론 7-1-4강. 타입의 분류(Classification of Types) (0) | 2019.12.12 |
프로그래밍 언어론 7-1-3강. 직교성(Orthogonality) (0) | 2019.12.12 |