360 likes | 694 Views
Chapter 6 Data Types. Programming Languages. 데이터 타입 (Data Types). 데이터 타입은 데이터 객체의 집합과 그 객체에 적용될 수 있는 미리 정의된 연산의 집합을 정의한다 . 데이터 타입의 발전 FORTRAN I (1957) – INTEGER, REAL, array Ada (1983) – 사용자는 문제에 필요한 모든 종류의 변수 타입을 정의할 수 있다 . 정의 기술자 (Desciptor) : 변수의 속성에 대한 집합
E N D
Chapter 6 Data Types Programming Languages
데이터 타입(Data Types) • 데이터 타입은 데이터 객체의 집합과 그 객체에 적용될 수 있는 미리 정의된 연산의 집합을 정의한다. • 데이터 타입의 발전 • FORTRAN I (1957) – INTEGER, REAL, array • Ada (1983) – 사용자는 문제에 필요한 모든 종류의 변수 타입을 정의할 수 있다. • 정의 • 기술자(Desciptor) : 변수의 속성에 대한 집합 • 프로그래밍 언어가 좋다는 것에 대한 중요한 척도 중의 하나는 문제에 적합한 변수를 모델링 할 수 있는 데이터 타입의 능력이 어느 정도이냐 하는 것이다 • 모든 데이터 타입 설계 시 고려 사항: • 변수를 참조하기 위한 문법은 무엇인가? • 어떠한 연산이 정의되며, 어떻게 지정되는가?
single 8(exp) 23(fraction) double 11(exp) 52(fraction) 기본 데이터 타입 • 정수 • 거의 하드웨어에서 제공하는 그대로 사용, 따라서 적용이 쉽다 • 한 언어에 8 가지의 정수 타입이 있을 수 있다 • 음수를 나타내는 방법 • Two’s complement (2의 보수) • One’s complement (1의 보수) • Sign bit • 부동 소수점(Floating Point) • 실수를 모델링한 것이지만, 근사값이다 • 과학 계산용 언어는 2 가지 이상의 부동 소수점 타입을 제공; 그 이상도 있을 수 있다 • 하드웨어에서 제공하는 대로 사용; 때로는 언어에서 유효숫자를 정의할 수도 있다 • 예(Ada) type SPEED is digits 7 range 0.0..1000.0; type VOLTAGE is delta 0.1 range -12.0..24.0; • 부동 소수점의 표현 방법
기본 데이터 타입 • 고정 소수점 • 상업용으로 사용(돈의 액수를 표시할 때) • 소수점 이하를 고정시켜 저장 • 장점 : 정확성 • 단점 : 제한된 범위 안에서만 가능, 메모리 낭비 • 부울 • 비트 단위로 구현하지만, 바이트를 사용할 경우도 있다 • 장점 : readability • 문자 • 숫자코딩으로 저장 (예 : ASCII, Unicode)
문자 스트링 타입 • 값은 문자의 연속이다(sequences of characters) • 설계시 고려 사항: • 기본 타입으로 할 것인가 아니면 배열의 특별한 경우로 할 것인가? • 객체의 길이가 정적인가 동적인가? • 연산: • Assignment • Comparison (=, >, etc.) • Catenation • Substring reference • Pattern matching
문자 스트링 타입 - 언어에서의 예 • Pascal • 기본 타입이 아니다; 할당문과 비교 연산 만이 가능 (of packed arrays) • Ada, FORTRAN 77, FORTRAN 90, BASIC • 어느 정도는 기본 타입 • Assignment, comparison, catenation, substring reference • FORTRAN은 pattern matching 기능도 가지고 있다 • 예 (Ada) N := N1 & N2 (catenation) N(2..4) (substring reference) • C와 C++ • 기본 타입이 아니다 • char 배열과 연산을 제공하는 라이브러리 함수를 사용 strlen strcpy strcat …
문자 스트링 타입 - 언어에서의 예 • SNOBOL4 (a string manipulation language) • 기본 타입 • 패턴 매칭을 포함하여 많은 연산이 있다 letter = ‘abcdefghijklmnopqrstuxyz’ wordpat = break(letter) span(letter). word • Perl과 JavaScript • 패턴은 regular expressions로 정의 • 매우 강력한 기능 • 예 : /[A-Za-z][A-Za-z\ㅇ] + / • Java – String 클래스 (char의 배열로서가 아님) • 객체는 변경될 수 없다. • Stringbuffer는 변경 가능한 string 객체에 대한 클래스이다
문자 스트링 타입 • 스트링의 길이: • 정적- FORTRAN 77, Ada, COBOL • 예 : (FORTRAN 90) CHARACTER (LEN = 15) NAME; • 제한된 동적 길이- C and C++ • 실제 길이는 널 문자에 의해 지정 • 동적- SNOBOL4 • 문자 스트링 타입의 평가: • writability에 도움을 준다 • 정적 길이이면서 기본 타입일 경우 구현하는 것이 용이하다 • 동적 길이이면 좋지만 구현 및 실행 시 비용이 많이 든다
문자 스트링 타입 • 구현: • 정적 길이- 컴파일 시간에 기술자(descriptor)를 유지 • 제한된 동적 길이- 길이를 위한 실행 시간 기술자가 필요 • C와 C++에서는 불필요 • 동적 길이 - 실행 시간에 기술자가 필요 • allocation/deallocation 이 가장 큰 문제 static str limited D.S length Max length address Current length address <Compile-time descriptor for static strings> <Run-time descriptor for limited dynamic strings>
사용자 정의 Ordinal 타입 • Ordinal 타입은 사용 가능한 값의 범위가 정수의 집합과 쉽게 관련 지어 생각할 수 있는 타입을 말한다 • 열거형 타입 - 기호 상수로 정의된 사용 가능한 값을 사용자가 나열한 타입이다 type DAYS is (Mon, Tue, Wed, Thu, Fri, Sat, Sun) • 설계시 고려사항 : 기호 상수가 하나 이상의 타입 정의에 속할 수 있을까? • Pascal • 상수를 재사용할 수 없다; 배열 첨자로 사용될 수 있다, for 의 변수, case selectors; • 입출력으로 사용 불가능; 비교될 수 있다 • Ada • 상수가 재사용될 수 있다(overloaded literals); • 타입 이름을 앞에 붙여 사용하므로 애매하지 않다; Pascal에서처럼 사용된다; • 입출력으로 사용이 가능하다 type LETTERS is (‘A, ..,’Z’) type VOWELS is (‘A’,’E’,’I’,’O’,’U’) for LETTER in ‘A’..’U’ loop ---- 이 경우 애매하다 for LETTER in VOWEL(‘A’) .. VOWEL(‘U’) loop
사용자 정의 Ordinal 타입 • C와 C++ • 정수로서 입출력으로 사용될 수 있는 것을 제외하고 Pascal과 비슷하다 • Java • 열거형을 포함하지 않지만 Enumeration 인터페이스를 제공 • 평가 : • readability에 도움을 준다--예: 색을 숫자로 표현할 필요가 없다 • reliability에 도움을 준다--예: 컴파일러가 연산과 값의 범위를 검사할 수 있다 • 연산 : 색에 연산을 할 수 없다. • 값의 범위 : 7가지 색만 사용하고 1..7 범위를 값을 사용한다면, 9도 오류가 아니다.
사용자 정의 Ordinal 타입 • 부분범위 타입(subrange) - ordinal 타입의 원소를 부분적으로 선택하되 연속적이며 순서가 정해지도록 한 타입 • 설계시 고려사항 :어떻게 사용할 것인가? • Pascal • 부분범위 타입은 그것의 부모 타입과 같은 방법으로 작동; for 변수와 배열의 첨자로 사용가능 • e.g. type pos = 0 .. MAXINT; • Ada • 서브타입은 새로운 타입이 아니다; 약간의 제약이 가해진 것 뿐이다 : compatible; • Pascal에서처럼 사용되며 + case constants • 예: subtype POS_TYPE is INTEGER range 0 ..INTEGER'LAST; • 평가: • readability에 도움을 준다 • Reliability - 제한된 범위는 에러 검사에 도움을 준다
배열(Arrays) • 배열은 같은 종류의 원소의 집합이면서, 첫번째 원소로부터의 상대적 위치에 의해 각각의 원소를 찾아낼 수 있다 • 설계시 고려 사항: • 첨자를 위해서는 어떠한 타입이 적법한가? • 첨자식이 원소 참소의 범위에 있는지 검사가 가능한가? • 첨자의 범위는 언제 바인드되는가? • 할당은 언제 되는가? • 첨자의 최대 개수는 얼마인가(차원)? • 배열을 초기화하는 것이 가능한가? • 조각(slice)이 허용되는가? • 원소의 참조 • Indexing : 인덱스 -> 원소 • 예) map(array_name, index_value_list) -> an element • FORTRAN, PL/I, Ada : 괄호 사용 • ALGOLs, Pascal, C : 대괄호 사용 • 첨자 타입: • FORTRAN, C - 정수만 • Pascal - ordinal 타입 (int, boolean, char, enum) • Ada - 정수 혹은 나열형(부울과 문자형 포함) • Java : 정수만 허용
배열(Arrays) • 배열의 네가지 종류 (첨자와 메모리 바인딩에 기초하여) • Static • 첨자의 범위와 메모리 바인딩이 정적 • 예 : FORTRAN 77, Ada에서 일부 배열 • 장점: 수행이 효율적 (allocation/ deallocation이 필요 없다) • Fixed stack dynamic • 첨자의 범위는 정적으로 바인드, 메모리는 elaboration time에 • 예 : 대부분의 Java 지역변수와 static 이 아닌 C의 지역 변수 • 장점 : 메모리가 효율적이다
배열(Arrays) • Stack-dynamic • 첨자의 범위와 메모리 바인딩이 동적, 그러나 한번 바인드되면 수명기간 동안에 고정되어 있다 • 예 : Ada declare blocks declare STUFF : array (1..N) of FLOAT; ... end; • 장점 : 유연성 - 크기는 배열이 사용되기 전까지 알 필요가 없다 • Heap-dynamic • 첨자의 범위와 메모리 바인딩이 실행하는 동안에 고정되어 있지 않다 • FORTRAN 90 • INTEGER, ALLOCATABLE, ARRAY (:,:) :: MAT (MAT을 동적 2-dim array로 선언) • ALLOCATE (MAT (10, NUMBER_OF_COLS)) (MAT가 10 rows 와 NUMBER_OF_COLS columns을 가지도록 할당) • DEALLOCATE MAT (MAT의 메모리를 Deallocate) • APL, Perl, JavaScript에서는 필요에 따라 배열이 증가하거나 축소된다. • Java에서는 모든 배열이 객체이다
배열(Arrays) • 첨자의 개수 • FORTRAN I : 3 차원까지 허용 • FORTRAN 77 : 7 차원까지 허용 • C : 1 차원까지 허용하지만 원소는 배열이 될 수 있다 • 기타 : 제한이 없다 • 배열 초기화 • 배열 원소가 메모리에 저장되는 순서대로 값을 나열 • FORTRAN : DATA 문장을 사용하거나 변수 선언시 / ... /안에 값을 넣는다 INTEGER LIST(3) DATA LIST /0,5,5/ • C와 C++ : { } 안에 값을 넣는다; 컴파일러가 알아서 입력 int stuff[] = {2, 4, 6, 8}; • Ada : 값에 대한 위치를 지정할 수 있다 SCORE : array (1..14, 1..2) := (1 => (24, 10), 2 => (10, 7), 3 =>(12, 30), others => (0, 0)); • Pascal과 Modula-2 : 배열 초기화를 허락하지 않음
배열(Arrays) • 배열 연산 • APL • 상당히 많다 • Ada • assignment; RHS은 배열 이름보다는 aggregate constant • catenation; 일차원 배열에 대해서만 허용 • relational operators (=와/= 만 허용) • FORTRAN 90 • 여러 가지 배열 연산이 기본으로 제공 • 예 : matrix multiplication, vector dot product
배열(Arrays) • Slices : 배열의 부분 구조; 단지 참조하기 위한 방법으로 사용 • FORTRAN 90 INTEGER MAT (1 : 4, 1 : 4) MAT(1 : 4, 1) - 첫 번째 행 MAT(2, 1 : 4) - 두 번째 열 • Ada • 일차원 배열만 가능 LIST(4..10)
배열(Arrays) • 배열의 구현 • 접근함수(access function)가 배열에 있는 첨자식을 원소의 주소로 변환 • 열 우선(Row major (by rows)) 혹은 행 우선(column major order (by columns)) RM : (i-1)*n + j CM : (j-1)*m + i
배열(Arrays) Compile-time descriptors Compile-time description for single-dimensioned arrays A compile-time descriptor for a multidimensional array
레코드(Records) • 레코드는 각각의 원소가 이름에 의해서 식별되는 이질의 데이터 원소의 집합이다. • 설계시 고려 사항: • 참조를 어떻게 할 것인가? • 연산이 어떻게 정의되는가? • 레코드 정의 문법 • COBOL은 레코드의 내포 정도를 숫자로 나타낸다 • 다른 언어에서는 recursive 정의를 사용
레코드(Records) • 레코드 필드 참조 • COBOL field_name OF record_name_1 OF ... OF record_name_n (Middle of Employee-name of …) • 기타 (점(.)을 사용) record_name_1.record_name_2. ... .record_name_n.field_name (employee-record…) • Fully qualified references : 모든 레코드의 이름을 포함 • Elliptical references : 애매하지 않는 한 레코드 이름을 생략 한다 • Pascal과 Modula-2는 참조를 간단하게 하기 위해 with clause를 사용 01 Employee-record 02 Employee-name 05 First PIC is X(20) 05 Middle PIC is X(10) 05 Last PIC is X(20) 02 Hourly-rate PIC is 99V99 Employee-record: record employee-name; record First : string(1..20) Middle : string(1..20) Last : string(1..20) end record end record
레코드(Records) • 레코드 연산 • Assignment • Pascal, Ada, C 타입이 같으면 허용 • Ada에서는 RHS가 aggregate constant일 수 있다 • 초기화 • Ada는 aggregate constant를 사용하여 허용 • Comparison • Ada에서 = 와 /=; 하나의 피연산자는 aggregate constant가 될 수 있다 • MOVE CORRESPONDING • COBOL에서는 같은 필드 이름에 대해서만 move가 가능 • 레코드와 배열의 비교 • 첨자가 동적이기 때문에 배열 원소의 접근은 레코드 필드보다 느리다(필드 이름은 정적) • 동적 첨자가 레코드 필드 접근을 위해서 사용될 수 있지만 타입 검사가 안되고 느리다
레코드(Records) 레코드 타입의 구현 A compile-time descriptor for a record
유니온(Unions) • 유니온은 변수가 실행 시간 동안에 다른 시간에 다른 타입의 데이터를 저장할 수 있는 타입을 말한다 • 유니온 설계시 고려 사항: • 해야 된다면 어떤 종류의 타입 검사가 가능한가? • 유니온이 레코드와 합쳐져야 하는가?
유니온(Unions) : 언어에서의 예 • FORTRAN - with EQUIVALENCE INTEGER X REAL Y EQUIVALENCE (X,Y)
유니온(Unions) : 언어에서의 예 • Pascal – discriminated와 nondiscriminated unions • e.g. type intreal = record tagg : Boolean of true : (blint : integer); false : (blreal : real); end; • Pascal 언어 설계의 문제점: 타입 검사가 비효율적 • 사용자가 일관성이 없는 유니온을 만들 수 있다 (tag가 개별적으로 값을 받을 수 있기 때문) var blurb : intreal; x : real; blurb.tagg := true; { 정수} blurb.blint := 47; { ok } blurb.tagg := false; { 실수} x := blurb.blreal; { 정수를 실수에 할당 } • tag가 optional! - 두 번째와 4 번째 할당문이 필요 없음
유니온(Unions) : 언어에서의 예 • Ada - discriminated unions • Pascal & Modula-2 보다는 안전하다: • Tag가 반드시 있어야 한다 • 사용자가 inconsistent union 을 만드는 것이 불가능하다 • tag 만을 이용하여 할당할 수 없다 • 유니온을 할당할 경우에는 tag 값을 반드시 포함해야 한다 type SHAPE is (CIRCLE, TRIANGLE) FIGURE_1 : OBJECT type OBJECT (FORM: SHAPE) is FIGURE_2 : OBJECT (FORM => TRIANGLE) record case FORM is when CIRCLE => DIAMETER: FLOAT FIGURE_1 := when TRIANGLE => (FORM => CIRCLE, LEFT-SIDE : INTEGER; DIAMETER => 12) RIGHT-SIDE : INTEGER; FIGURE_2는 바뀔 수 없다 ANGLE : FLOAT; end case end record
유니온(Unions) : 언어에서의 예 • C와 C++ - free unions (tag가 없다) • tag가 레코드에서 선언되지 않는다 • 참조시 타입 검사를 하지 않는다 • 평가 : Ada를 제외하고는 모든 언어에서 안전하지 않다 • 구현 : 예 type NODE(TAG: boolean) is record case TAG is when true => count : integer; when false => sum : float; end case
집합(Sets) • 집합은 ordinal 타입으로부터 순서가 정해지지 않은 서로 다른 값을 저장할 수 있는 변수 타입이다 • 설계시 고려 사항:집합 타입이 가질 수 있는 원소 최대 개수는 얼마인가? • Pascal • 언어 정의시 최대 개수는 정하지 않았다 (최개 개수가 너무 작으면 portable 하지 않고, writability가 떨어진다) • 연산 union (+), intersection (*), difference (-), =, <>, superset (>=), subset (<=), in • Modula-2와 Modula-3 • 추가의 연산자: INCL(S=S+{I}), EXCL(S=S-{I}, / (symmetric set difference (한 집합에는 속하지만 두 집합에는 들어 있지 않음)) • Ada • 집합을 포함하지 않지만, 모든 열거형 타입에 in으로 정의된 멤버쉽 연산자가 사용 가능
포인터(Pointers) • PL/I 포인터의 문제점: • 타입 검사가 불가능 - unrestricted domains 때문에 • Dangling 포인터 (위험) : deallocate된 변수의 주소를 가지고 있는 경우 • Explicit deallocation (어떤 객체를 할당한 후 두 번째 포인터도 그것을 지정; 객체를 deallocate) new(p1); new(p2); p2=p1; dispose(p1); /* p2는 dangling pointer */ • Dangling object • 유용한 데이터를 포함하고 있지만 더 이상 사용할 수 없는 object, garbage (낭비이며, 위험) new(p1); new(p1);
포인터(Pointers) : 언어에서의 예 • Pascal: 동적 메모리 관리에만 사용 • Explicit dereferencing • Dangling 포인터가 가능(dispose) • Dangling 객체도 가능 • Ada: Pascal과 Modula-2보다는 낫다 • 동적 객체는 그것의 스코프를 벗어나면 자동적으로 deallocate되기 때문에 dangling 포인터가 안 생길 수도 있다 (explicit deallocation이 없다) • 모든 포인터는 null로 초기화된다 • dangling 객체 문제는 PL/I과 비슷 - 그러나 거의 일어나지 않는다
포인터(Pointers) : 언어에서의 예 • C와 C++ • 동적 메모리 관리와 addressing을 위해 사용 • Explicit dereferencing와 address-of operator • 제한된 범위 안에서 산술 연산이 가능 • e.g. real stuff[100]; real *p; p = stuff; *(p+5) = stuff[5] and p[5] *(p+i) = stuff[i] and p[i] • void * • 어떤 종류의 타입도 지적할 수 있다; 타입 검사도 가능 (dereference는 불가능) The assignment operation j = *ptr
포인터(Pointers) : 언어에서의 예 • FORTRAN 90 포인터 • heap과 non-heap 변수를 지적할 수 있다 • Implicit dereferencing • non-dereferenced references를 위한 특별 할당 연산자를 제공 ptr => target (target : 포인터, 주소만 할당) • Non-heap variables that will be pointed to must be specially declared, as in: INTEGER, TARGET::NODE INTEGER, ORANGE NODE => ORANGE (X) 불가능 (TARGET is an attribute)
포인터(Pointers) : 언어에서의 예 • C++ Reference Types • dereference가 가능한 Constant 포인터 int result = 0; int &ref_result = result; (result와 ref_result는 alias) • 파라메터로 사용 가능 • pass-by-reference 와 pass-by-value의 장점 • Java – reference만 가능 • Not pointer arithmetic • 객체에 대해서만 pointer를 사용가능 • no explicit deallocator • dangling reference가 생기지 않는다 • dereferencing은 언제든지 가능
포인터(Pointers) • 포인터의 평가: • Dangling pointers와 dangling objects 가 문제 • 포인터는 goto문장처럼 변수에 의해 접근 가능한 메모리의 범위를 넓게 만든다 • 포인터는 필요하다 • 포인터 없이 언어를 설계할 수 없다