6장 데이터 타입 2017. 4. 24 순천향대학교 컴퓨터공학과 하 상 호
이 장에서는? 다양한 데이터 타입에 대해서 설계 고려사항, 언어 예제, 평가, 구현 사항 등을 살펴본다. 기본데이터 타입 문자 스트링 타입 사용자-정의 순서 타입 배열 타입 연상 배열 레코드 타입 튜플 타입 리스트 타입 공용체 타입 포인터 타입과 참조 타입 타입 검사, 강 타입, 타입 동등 규칙
서론 데이터 타입이란? 값들의 모임과 이러한 값들에 대한 미리 정의된 연산들의 집합으로 정의된다 프로그램의 데이터 조작 작업 용이성을 결정하는 중요한 요소는 언어의 데이터 타입들이 문제의 실세계의 객체들과 얼마나 잘 매칭되는가에 따른다. 십진수 타입, 불리안 타입 구조체 정의 사용자-정의 타입 추상 데이터 타입
서론 타입 시스템이란? 타입 시스템의 용도 구조화된 타입은 타입 연산자나 구성자로 정의 언어의 각 식에 대해서 타입이 어떻게 연관되는지를 정의하고, 타입 호환성, 타입 동등을 위한 규칙을 포함 => 프로그래밍 언어의 의미론 이해에 있어서 중요 타입 시스템의 용도 오류 탐지 <- 타입 검사 프로그램 모듈화 지원 <- 모듈간 인터페이스 검사 프로그램 문서화(documentation) <- 타입 선언 (데이터 정보의 문서화) 구조화된 타입은 타입 연산자나 구성자로 정의 C의 타입 연산자: [], * 타입 구성자: struct, record
서론 서술자(descriptor) 데이터 타입에 대한 공통된 설계 고려사항 서술자는 변수의 속성들의 모임 타입 검사, 할당/회수에 활용 속성 유형: 정적 vs. 동적 데이터 타입에 대한 공통된 설계 고려사항 타입에 대해서 어떠한 연산들이 정의되어 있고, 이러한 연산들이 어떻게 명세되는가?
기본 데이터 타입 대부분의 프로그래밍 언어는 기본 데이터 타입(primitive data types)들의 집합을 제공 기본 데이터 타입이란? 다른 데이터 타입의 관점에서 정의되지 않는 타입 단지 하드웨어의 반영이거나 약간의 비 하드웨어적 지원 기본 테이터 타입 종류 수치 타입: 정수, 부동 소수점, 십진수, 복소수 불리안 타입 문자 타입
기본 데이터 타입: 정수 하드웨어의 정확한 반영 다양한 크기의 정수 지원 Ex. Java의 부호 정수: byte, short, int, long
기본 데이터 타입: 부동 소수점 실수를 그 근사 값으로 모델링 방법: 소수점 이하 부분과 지수 부분으로 표현 ex. ∏, e 등 부동 소수점 수는 유한 개의 이진수로 표현 불가능(ex. 0.1) 방법: 소수점 이하 부분과 지수 부분으로 표현 2가지 실수 타입: float/ double IEEE 부동-소수점 표준 754 형식 단정도 배정도
기본 데이터 타입: 복소수 복소수는 그 값이 순서화된 부동 소수점 수의 쌍 (실수부, 허수부)로 표현: 리터럴 형식: (7 + 3i) in Python Ex. Fortran, Python, C99
기본 데이터 타입: 십진수 고정된 개수의 십진수 디지트를 BCD(binary coded decimal) 형식으로 저장 장점: 정확성(십진수 값을 정확하게 표현) 단점: 제한된 범위, 메모리 낭비 Ex. COBOL, C#
기본 데이터 타입: 불리안 값들의 범위는 단지 참, 거짓의 2가지 대부분 범용 언어에서 지원 흔히 바이트로 구현 판독성 향상 C99, C++, Java, C#, VB
기본 데이터 타입: 문자 문자 데이터는 수치 코딩으로 저장 코딩 기법: ASCII (8bits): American Standard Code for Information Interchange) 16-bit Unicode 32-bit Unicode
문자 스트링 타입 문자 스트링 타입(character string type)은 값들이 일련의 문자들로 구성 설계 고려사항 기본 타입인가? 아니면 배열의 특정 유형인가? 스트링의 길이가 정적인가? 아니면 동적인가?
문자 스트링 타입 연산 전형적인 연산들 배정 비교(=, >, 등) 접합 부분 스트링 참조(substring reference) 패턴 매칭(pattern matching)
문자 스트링 타입: 언어 예 C C++ Java Python Perl, JavaScript, PHP 기본 타입이 아니고, char 배열로 제공 스트링 연산을 표준 라이브러리로 제공 C++ char 배열, string 클래스 Java String, StringBuffer 클래스 Python 스트링 기본 타입 지원 (Java의 String과 유사: 변경 불가) 다양한 스트링 연산 제공 Perl, JavaScript, PHP 스트링 기본 타입 지원 정규식을 이용한 패턴 매칭 연산 제공 (C++, Java, C# 지원) /[A-Za-z][A-Za-z\d]+/ /\d+\.?\d*|\.\d+/
스트링 길이 선택 사항 정적 길이 스트링( static length string) 스트링 생성시 그 길이가 설정되고 고정 Ex. Python 스트링, Java의 String, C++ string, C# String 제한된 동적 길이 스트링(limited dynamic length string) 스트링 선언시 고정된 최대 길이까지의 가변적인 길이를 갖는 것을 허용 C/C++ 동적 길이(dynamic length string) 최대 길이 제한 없이 가변 길이를 갖는 것을 허용 최대의 유연성, 동적 할당/회수 부담 Perl, JavaScript, C++
스트링 타입 평가 작성력 향상 단순 패턴 매칭이나 접합과 같은 연산은 필수적 배열보다는 기본 타입으로 다루는 것이 자연스럽다 단순 패턴 매칭이나 접합과 같은 연산은 필수적 오늘날 언어에서 기본 스트링 타입을 지원하지 않는 것은 정당화하기 어렵다
스트링 타입 구현 정적 길이 제한된 동적 길이 동적 길이 컴파일시간 서술자 현재 길이에 대한 실행시간 서술자 필요 C/C++에서 실행시간 서술자가 필요한가? 동적 길이 실행시간 서술자 필요 할당/회수에 따른 복잡한 기억공간 관리 필요
사용자-정의 순서 타입 순서 타입(ordinal type)은 가능한 값들의 범위가 양의 정수 집합과 연관 가능한 타입 Java의 기본 타입 중에서 순서 타입은? 사용자-정의 순서 타입 열거 타입 부분 범위 타입
열거 타입 열거 타입(enumeration type)은 모든 가능한 값들이 그 정의에서 제공되는, 즉 나열되는 타입 이 타입은 열거 상수(enumeration constants)라 불리는 이름 상수들의 모임을 정의하고, 그룹핑하는 방법을 제공 Ex. In C, enum days {Mon, Tue, Wed, Thu, Fri, Sat, Sun}; 열거 상수에는 묵시적으로 0, 1, .. 등의 정수가 순차적으로 할당
열거 타입 설계 고려사항 한 열거 상수가 한 개 이상의 타입 정의에 올 수 있는가? (그럴 경우에, 그러한 상수 참조에 대한 타입 검사가 어떻게 이루어지는가?) 열거 타입이 정수로 강제 변환 가능한가? 다른 타입이 열거 타입으로 강제 변환 가능한가?
열거 타입 예제 // in C enum colors {red, blue, green, yellow, black}; // 디폴트 내부값은 0, 1, … int main() { enum colors myColor = blue, yourColor = red; … myColor++; // 적법한가? myColor = 4; // 적법한가? }
열거 타입 언어 예 평가 C, C++, Java 5.0, C# 판독성 향상: 이름 상수가 코딩된 값보다 쉽게 인식 신뢰성 향상 열거 타입에 대한 산술 연산이 의미가 있는가? 열거 타입 변수에 범위를 벗어난 값을 배정 가능한가?
부분 범위 타입(subrange types) 예제: 12..18 언어 예: in Ada, type Days is (mon, tue, wed, thu, fri, sat, sun); subtype Weekdays is Days range mon..fri; subtype Index is Integer range 1..100; Day1: Days; Day2: Weekday; Day2 := Day1; // 컴파일러는 범위 검사 코드 생성 기존 타입에 대한 제약은 가능한 값들의 범위 부모 타입에 대해서 정의된 모든 연산은 명세된 범위 밖의 값들에 대한 배정을 제외하고는 부타입에 대해서도 정의
부분 범위 타입 평가: 판독성 향상 신뢰성 향상 최근의 언어에서 지원되지 않는 경향 부분 범위 타입 변수는 특정 범위의 값만을 저장할 수 있음을 알려줌 신뢰성 향상 명세된 범위를 벗어난 값을 부분 범위 변수에 배정하면 오류로 탐지 최근의 언어에서 지원되지 않는 경향
배열 타입 배열(array)은 동질적인(동일한 타입을 갖는) 데이터 원소들의 집단체(aggregate)이고, 개개의 원소는 그 집단체의 첫번째 원소에 상대적인 위치로 식별 설계시 고려사항 어떤 타입이 첨자에 대해서 적법한가? 원소 참조시 첨자 식이 범위 검사되는가? 첨자 범위는 언제 바인딩되는가? 배열 할당은 언제 일어나는가? 톱니형 또는 직사각형 다차원 배열이 허용되는가? 또는 둘 다 허용되는가? 배열이 할당될 때, 초기화 가능한가? 슬라이스(slice)가 존재한다면, 어떤 종류의 슬라이스가 지원되는가?
배열 인덱싱 인덱싱은 인덱스로부터 원소로의 사상을 의미 인덱스 구문 arrayName (인덱스 리스트) => 원소 괄호 사용 FORTRAN, PL/I, Ada 배열 참조와 함수 호출간의 균일성(uniformity)를 보여준다: 이 둘 모두 사상(mapping)을 의미 대괄호 사용 다른 대부분의 언어
배열 인덱스(첨자) 타입 첨자 타입 인덱스 범위 검사 FORTRAN, C: 정수만 가능 Ada: 정수, 열거, 불리안, 문자 등 임의 순서 타입 Java: 정수만 가능 인덱스 범위 검사 C, C++, Perl, FORTRAN: 범위 검사 명세하지 않음 Java, C#: 범위 검사 명세 Ada: 디폴트는 범위 검사 요구하나 프로그래머에 의해서 무위화 가능
첨자 바인딩 및 배열 유형 배열 변수의 첨자 타입의 바인딩은 보통 정적이지만, 그 첨자 값 범위는 때때로 동적으로 바인딩 첨자 범위 하한이 묵시적으로 0,1, 또는 임의 정수 값으로 설정 가능 첨자 범위가 프로그래머에 의해서 명세 첨자 범위 바인딩 시기, 기억공간 바인딩 시기 및 그 할당 위치에 기준하여 배열을 5가지로 유형화 정적 고정 스택-동적 스택-동적 고정 힢-동적 힢-동적
첨자 바인딩 및 배열 유형(계속) 정적 배열(static array)은 첨자 범위가 정적으로 바인딩, 기억공간 할당이 정적 장점: 효율적(efficiency) 예: C/C++의 static 배열 고정 스택-동적 배열(fixed stack-dynamic array)은 첨자 범위는 정적 바인딩, 기억 공간은 선언문 세련화시간에 할당 장점: 기억공간의 효율적 예: C/C++의 함수 내부에 선언된 배열
첨자 바인딩 및 배열 유형(계속) 스택-동적 배열(stack-dynamic array)은 첨자 범위와 기억공간 할당이 모두 세련화 시간에 동적 바인딩. 이러한 바인딩은 변수 존속기간 동안 고정 장점: 유연성 (배열의 크기를 사용 전까지 알 필요없음) 예제: in Ada, Get(List_Len); declare List: array(1..List_Len) of Integer; begin … end;
첨자 바인딩 및 배열 유형(계속) 고정 힙-동적 배열(fixed heap-dynamic array)은 첨자 범위와 기억 공간 바인딩이 실행중 사용자 프로그램이 요청할 때 이루어지고, 힙으로부터 할당. 바인딩 이후는 고정 유연성 vs. 할당 시간 언어 예 C, C++의 동적 배열 Java, C#의 배열
첨자 바인딩 및 배열 유형(계속) 힙-동적 배열(heap-dynamic array)은 첨자 범위, 기억 공간 바인딩이 동적, 이후 바인딩은 변경 가능 유연성 vs. 할당 및 회수 부담 언어 예: Java의 ArrayList, C#의 List Perl, JavaScript ArrayList band = new ArrayList(); Band.add(“Paul”); Band.add(“Pete”); … System.out.println(“band.get(1));
배열 초기화 배열의 기억공간 할당 시점에 그 배열을 초기화하는 수단을 제공 예제 int list[] = {4, 5, 7, 83}; char name[] = “Gildong”; char *names[] = {“Bob”, “Jake”, “Joe”}; String[] names = {“Bob”, “Jake”, “Joe”}; // in Java
배열 연산 배열 연산은 배열 단위의 연산을 수행 언어 예 공통된 배열 연산: 배정, 접합, 동등/비동등 비교, 슬라이스 APL: 가장 강력한 배열 처리 언어 4가지 산술연산이 벡터와 행렬에 대해서 정의 벡터(V)와 행렬(M)에 대한 단항 연산자 제공 Perl: 배정 허용, 비교는 허용하지 않음 Python: 배정, 접합(+), 원소 멤버쉽(in) 허용, 비교 허용 C 기반 언어: ΦV: V의 원소를 역순으로 ΦM: M의 열을 역순으로 θM: M의 행을 역순으로 ØM: M의 전치행렬 계산 ÷M: M의 역행렬 계산
직사각형 배열 vs. 톱니형 배열 직사각형 배열(rectangular arrays)은 모든 행이 동일한 개수의 원소를, 모든 열이 동일한 개수의 원소를 갖는 다차원 배열 정확히 직사각형 테이블을 모델링 언어 예: Fortran, Ada, C# myArray[3, 7] 톱니형 배열(jagged arrays)은 행들의 크기가 동일할 필요가 없는 다차원 배열 다차원 배열에서, 배열의 원소가 배열인 경우(“an array of arrays”) 언어 예: C, C++, Java, C# myArray[3][7] // in C# int [][]ma = new int [MAX][]; // in Java for (int i = 0; i <= MAX; i++) ma[i] = new int [i+1];
슬라이스 슬라이스(slice)는 배열의 부분적 구조 배열 일부분에 대한 참조 메커니즘을 제공 배열 연산을 제공하는 언어에서 유용
슬라이스 예제 In Fortran 95, Vector(3:6) Mat(1:3, 2) Mat(2:3, 1:3) Cube(2, 1:3, 1:4) Cube(1:3, 1:3, 2:3) Integer, Dimension (10) :: Vector Integer, Dimension (3, 3) :: Mat Integer, Dimension (3, 3, 4) :: Cube
배열 구현 배열 원소 접근 함수 구현 1차원 배열의 원소 접근 함수 배열 원소에 대한 첨자 식을 원소의 주소로 사상 사상 코드는 컴파일러가 생성 1차원 배열의 원소 접근 함수 In C, 주소(list[k]) = 주소(list[k]) = 주소(list[하한]) + (k-하한)*원소_크기 다차원 배열의 경우는?
배열 구현 다차원 배열의 저장 순서 행-우선 순서(row major order): 대부분의 언어 열-우선 순서(column major order): Fortran Ex. 3 5 7 1 3 8 6 2 5
배열 구현 다차원 배열에서 접근 함수 (행-우선 순서) C의 a[m][n] 배열에서, 주소(a[i][j]) = 주소(a[i,j]) = 주소(a[0,0]) + ((i번째 행보다 앞선 행의 개수)*(열의 크기) + (j번째 열의 왼쪽에 위치한 원소 개수) *원소_크기 3차원 배열의 경우는?
배열 구현 서술자 배열 원소 접근 함수에 필요한 정보 포함 색인 범위에 대한 실행시간 검사에 필요 첨자 범위의 정적/동적에 따른 컴파일-시간, 실행시간-시간서술자 필요 일차원 배열 다차원 배열
배열 매개변수에서 첫번째 첨자는 생략 가능한가? 배열 구현 언어 예 In C 배열 매개변수에서 첫번째 첨자는 생략 가능한가? double sum(double a[], int n) {…} int sum (int a[][5], int n, int m) {…}
연상 배열 연상 배열(associative array)은 원소들간에 순서가 없으며, 키 값을 통해서 원소에 접근하는 배열 사용자-정의 키가 원소와 함께 저장되어야 한다. 언어 예 Perl, Python에서는 내장 타입으로 지원, Java, C++, C#에서는 클래스 라이브러리에 의해서 지원 In Perl, %hi_temp = {“Mon”=>77, “Tue”=>79, “Wed”=> 65, …); $hi_temp {“Wed”} = 83;