2.1 기본 내장 타입
● C++에서 정의하는 기본 타입에는 산술 타입과 void라는 특별한 타입이 있다.
○ 산술 타입 : 문자, 정수, 부울 값, 부동소수점 수 등등
○ void 타입은 연관된 값 x, 제한된 일부 상황에서만 사용 가능
2.1.1 산술 타입
● 산술 타입
○ 1. 정수 타입 : 문자와 부올울 타입 포함
○ 2. 부동소수점 타입
● 비트 수로 나타내는 산술 타입 크기는 시스템마다 다름
● bool 타입 : true 와 false의 진리 값을 나타내다.
● 부동소수점 타입 : 단정도, 배정도, 확장 정밀도 값을 나타낸다.
● 부호 있는 타입과 부호 없는 타입
○ bool과 확장 문자 타입을 제외한 정수 타입은 부호 있는 타입이거나 부호 없는 타입이다.
○ 기본 문자 타입은 char, signed char, unsigned char 세가지로 구분
● 사용할 타입 결정하기
○ 음수가 될 수 없을 떄는 부호 없는 타입을 사용한다.
○ 정수 연산에는 int를 사용한다.
○ 산술 표현식에는 일반적인 char이나 bool을 사용하지 않는다.
○ 부동 소수점 계싼에는 double을 사용한다.
2.1.2 타입 변환
● 객체의 타입 : 객체가 담을 수 있는 데이터와 그 객체가 수행할 수 있는 연산을 정의
● 부호 있는 타입 객체에 범위를 벗어난 값을 대입하면 결과는 "미정의"
● 부호 없는 타입을 포함한 표현식
○ 피연산자 하나 또는 둘 모두가 부호 없는 타입이든 그렇지 않든, 부호 없는 타입에서 값을 뺄 떄는 결과가 음수가 아닌지 확인해야 한다.
● 부호 있는 타입과 부호 없는 타입을 섞여 쓰지 않느다.
2.1.3 상수
● 42와 같은 값은 그 값 자체로 명확하므로 상수라고 한다. 모든 상수에는 타입이 있으며, 상수의 형식과 값에 따라 타입이 결정된다.
● 정수와 부동소수점 상수
○ 0으로 시작 - > 8진수, 0x or 0X로 시작 -> 16진수
● 문자와 문자열 상수
○ 문자열 상수의 타입은 상수 char 배열
○ 서로 이웃하며 공백 문자, 탭, 줄바꿈 문자로만 나뉜 두 문자열 상수는 문자열 상수 하나로 합칠 수 있다.
● 확장 문자열
○ 출력할 수 없는 문자를 출력할 수 있게 확장 문자열을 사용한다. ' \ '로 시작한다.
● 상수 타입 지정
○ 접미어 또는 접두어를 사용해 정수, 부동소수점, 문자 상수의 기본 타입을 바꿀 수 있음
2.2 변수
● 변수는 프로그램에서 조작할 수 있는, 명명한 저장 공간이다.
2.2.1 변수 정의
int sum = 0, value, units_sold = 0;
Sales_item item;
● 객체란 무엇인가?
○ '객체' : 데이터를 저장하는 메모리 영역이며 타입이 있다.
■ 초기화
○ 초기화 : 객체를 만들만서 값을 지정하는 것
int a = 0;
int a = {0};
int a{0};
int a(0);
● 목록 초기화
○ 중괄로를 이용한 초기화 - > 목록 초기화
○ 초기 값 떄문에 데이터 손실이 생길 수 있으며 컴파일러에서는 내장 타입 변수에 초기화 목록 사용을 허용하지 않는다.
● 기본 초기화
○ 기본 초기화 : 초기 값 없이 변수를 정의하는 것
○ 함수 안에서 정의한 내장 타입 변수는 초기화 하지 않는다.
○ 어떤 클래스는 모든 객체를명시적으로 초기화해야 한다. 이런 클래스의 객체를 초기 값 없이 생성하려 하면 컴파일 오류 발생 2.2.2 변수 선언과 정의
● 분리 컴파일러 : 프로그램을 논리적인 여러 부분으로 나눠 만들 수 있도록 하는 것
● 선언 : 프로그램에 이름을 알리는 것
● 장의 : 연관된 개체를 만듦
● extern 키워드 사용 - > 정의가 아닌 선언 사용 가능
extern int i; // i를 선언하지만 정의하자 않는다.
int j; // j를 선언하면서 정의한다.
● 모든 내장 타입 객체는 초기화하길 권장
2.2.3 식별자
● 식별자는 문자, 숫자, 밑줄 문자로 만듦
● 변수 이름 규칙
○ 식별자는 그 자체로 의미를 나타냄
○ 변수 이름은 보통 소문자로 씀
○ 클래스는 보통 대문자 시작
○ 식별자를 여러 단어로 쓸 떄는 각 단어가 시각적으로 구분이 되도록 한다.
2.2.4 이름 유효 범위
● 유효 범위 : 프로그램에서 이름이 특별한 의미를 지니는 구역이며 c++에서 대부분의 유효 범위는 중괄호로 구분
● 전역 유효 범위 : 함수 밖에서 정의한 이름 대부분
● 구역 유요 범위 : 중괄호 안
● 변수는 처음 사용하는 곳에 정의한다
● 중첩된 유효 법위
○ 포함된 유효 범위 - > 내부 유효 범위 / 포함하는 유효 범위 - > 외부 유효 범위
○ 함수에서 사용하고 있거나 사용할 수도 있는 전역 변수와 같은 이름으로 지역 변수를 정의하는 것은 거의 언제나 좋지 않은 생각이다.
2.3 복합 타입
● 복합 타입 : 다른 타입을 사용해 정의한 타입
2.3.1 참조자
● 참조자는 객체에 별칭을 정의한다. 참조자로 '참조하는' 다른 타입이 곧 참조자 타입이다.
● 참조자 타입을 정의할 떄는 선언자를 &이름 형식으로 사용
● 참조자를 정의할 때는 초기 값을 복사하지 않고 참조자를 초기화식에 결합한다.
● 참조자는 별칭이다.
○ 참조자는 객체가 아니며, 이는 이미 존재하고 있는 객체에 대른 이름일 뿐이다
2.3.2 포인터
● 포인터는 다른 타입을 '가리키는' 복합 타입이다.
● 포인터는 그 자체로 객체이다.
● 대입하거나 복사 가능, 포인터 하나가 생명 주기 동안 여러 다른 객체를 가리킬 수 있음
● 초기화 x -> 미정의 값을 가리킴
● 정의 : *이름 / *이름은 포인터 변수마다 반복해 사용
● 객체 주소 얻기
○ 포인터는 다른 객체의 주소를 담고 있다. 객체의 주소는 주소연산자를 사용해 얻는다.
● 포인터 값
○ 1. 객체를 가리킬 수 있다.
○ 2. 객체의 마지막 요소 바로 다음 위치를 가리킬 수 있다.
○ 3. 어느 객체와도 결합하지 않았음을 나타내는 널 포인터일 수 있다.
○ 4. 유효하지 않을 수 있다. 즉 먼저 본 세가지 경우 외 다른 값일 수 있다.
● 포인터를 사용해 객체에 접근하기
○ 포인터로 객체를 가리키고 있으면 역참조 연산자를 사용해 객체에 접근 가능
● 널 포인터
○ 널포인터는 어느 객체도 가리키지 않으므로 포인털르 사용하기 전에 널인지 확인 하는게 좋음
● 대입과 포인터
○ 참조자는 객체가 아님
○ 모든 포인터는 초기화 한다.
● void* 포인터
○ void*포인터는 몯느 객체의 주소를 담을 수 있는 특별한 포인터 타입
○ 메모리를 메모리로 다루기 위해 사용
2.3.3 복합 타입 선언 이해하기
● 여러 변수를 정의하기
○ 타입 변경자는 단일 문장에서 정의한 모든 변수에 적용한다고 생각하는 것은 오해
● 포인터에 대한 포인터
○ 일반적으로 선언자에 적용할 수 있는 타입 변경자 수에는 제한이 없다.
● 포인터에 대한 참조자
○ 참조자는 객체 x -> 참조자에 대한 포인터 없음
○ 포인터는 객체 o -> 포인터에 대한 참조자 정의 가능
2.4 const 한정자●
const int bufsize = 512;
● 변수 타입을 const로 정의해 바뀌지 않도록 할 수 있다.
● 초기화와 const
○ 객체를 바꿀 수 없는 연산만 사용 가능
● 기본적으로 const 객체는 파일에 지역적이다.
○ const 변수의 초기 값이 상수 표현식이 아닐 때도 있음
○ const 객체를 여러 파일에서 공유하려면 그 변수를 extern으로 정의해야 한다.
2.4.1 const에 대한 참조자
● 참조자를 const 타입 객체에 결합할 수 있다.
● 보통의 참조자와 달리 const에 대한 참조자를 사용해 해당 참조자와 결합한 객체를 바꿀 수 없다.
● const 참조자는 const에 대한 참조자 이다.
● 초기화와 const에 대한 참조자
○ const에 대한 참조자는 const가 아닌 객체, 상수, 더 일반적인 표현식과 결합 가능
double dval = 3.14;
const int &ri = dval;
const int tmp = dval;
const int &ri = temp;
● const에 대한 참조자는 const가 아닌 객체를 참조할 수 있다.
○ const의 값은 변경 못하지만 변수는 변경 가능
2.4.2 포인터와 const
● const에 대한 참조자처럼 const에 대한 포인터도 가리키는객체를 바꿀 수 없다
● const에 대한 참조자처럼 const에 대한 포인터 역시 가리키는 객체가 const인지는 알 수 없다.
● const 포인터
○ 다른 const 객체처럼 const 포인터는 초기화해야 하며 초기화한 후에는 그 값, 즉 담고 있는 주소를 바꿀 수 없다.
○ 포이터 자체가 const라고 해도 이 포인터를 사용해 대상 객체를 바꿀 수 있는지는 알 수 없다.
int errNum = 0;
int *const currErr = &errNum;
const double pi = 3.14159;
const double *const pip = π
2.4.3 상위 const
● 상위 const : 포인터 그 자체가 const , 객체를 복사할 때는 상위 const를 무시
● 하위 const : 포인터가 const 객체를 가리킬 수 있는 것, 하위 const는 절대 무시하지 않는다.
2.4.4 constexpr과 상수 표현식
● 상수 표현식은 컴파일 중에 값을 평가할 수 있으며 그 값을 바꿀 수 없는 표현식이다.
const int max_files = 20; // 상수 표현식이다.
const int limit = max_files + 1; // 상수 표현식이다.
int staff_size = 27; // 상수 표현식이 아님
const int sz = get_size(); // 상수 표현식이 아님
● constexpr 변수
○ constexpr 선언을 사용해 변수가 상수 표현식인지 컴파일러에서 확인하도록 할 수 있다.
○ constexpr로 선언한 변수는 암시적으로 const이므로 상수 표현식으로 초기화해야 한다.
constexpr int mf = 20;
constexpr int limit = mf + 1;
constexpr int sz = size(); // size가 constexpr함수일 때만 성립
● 일반적으로, 상수 표현식으로 쓰려는 변수는 constexpr을 사용하는 것이 좋다.
● 상수 타입
○ 산술, 참조자, 포인터 타입이 상수 타입이다.
○ 포인터와 참조자 모두 constexpr에 정의할 수 있지만 초기화 하는데 사용하는 객체는 엄격히 제한
● 포인터와 constexpr
○ constexpr 선언에서 포인터를 정의하면 constexpr 지정자는 포인터로 가리키는 타입이 아니라 포인터에 적용한다.
2.5 타입 다루기
2.5.1 타입 별칭 ● 타입 별칭은 다른 타입과 동의어인 이름이다.
● typedef
typedef double weges; // weges == double
typedef weges base, *p // base == double, p == double*
● using
using SI = Sales_item;
● 타입 별칭은 타입 이름이므로 타입 이름을 쓸 수 있는 곳은 어디든 사용 가능
● 포인터, const와 타입 별칭
○ 개념적으로 별칭을 원래 타입으로 바꿔 타입 별칭을 사용하는 선언을 해석하려 시도는 할 수 있으나 올바르지 않을 수 있다.
2.5.2 auto 타입 지정자
● 새로운 표준에서는 auto 타입 지정자를 사용해 컴파일러가 타입을 알려 주도록 할 수 있다.
● auto를 타입 지정자로 변수에는 반드시 초기 값이 있어야 한다.
● 복합 타입, const와 auto
○ 1. 참조자를 사용하면 지금까지 본 것처럼 참조자로 참조하는 객체를실제로 사용한다.
○ 2. auto에서는 일반적으로 상위 const를 무시한다.
○ 추론한 타입에 상위 const가 있으려면 명시적으로 지정해야 한다.
2.5.3 decltype 타입 지정자
decltype(f()) sum = x;
● decltype 지정자는 피연산자 타입을 반환한다.
● 컴파일러에서는 타입을 결정하기 위해 표현식을 분석할 뿐 평가하지 않는다.
● decltype에서는 상위 const와 참조자를 포함해 대상 변수의 타입을 반환
● decltype과 참조자
○ decltype에서 하는 추론이 대상 표현식의 형식에 의존
2.6 데이터 구조 직접 정의하기
● c++에서는 클래스를 정의해 자신만의 데이터 타입을 직접 정의한다.
2.6.1 Sales_data 타입 정의하기
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
● 이 클래스는 struct 키워드로 만듦
● 클래스 본체는 중괄로 둘러싸므로 새 유효 범위를 형성
● 클래스 테이터 멤버
○ 데이터 멤버에 클래스 내 값을 사용할 수 있다.
2.6.2 Sales_data 클래스 사용하기
● 두 Sales_data 객체 더하기
○ Sales_data.h로 정의
● 데이터를 읽어 Sales_data 객체에 넣기
● 두 Sales_data 객체의 합 출력하기
2.6.3 헤더 파일 직접 만들기
● 함수 안에 클래스를 정의할 수 있는데 그런 클래스는 기능이 제한된다.
● 각 파일에서 해당 클래스 정의가 같음을 보장하기 위해 흔히 클래스를 헤더 파일에 정의한다.
● 전처리기에 대한 간략한 소개
○ 전처리기 : 헤더를 여러 번 포함하더라도 한전하게 하는 가장 일반적인 기술
○ C++프로그램에서는 전처리기를사용해 헤더 보호문을 정의한다.
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
std:: string bookNO;
unsigned units_sold = 0;
double revenue = 0.0;
};
#endif
○ 전처리기 변수 이름은 C++ 유효 범위 규칙에 따르지 않는다.
'C++ Primer' 카테고리의 다른 글
함수 (0) | 2024.07.02 |
---|---|
문장 (0) | 2024.06.29 |
표현식 (0) | 2024.06.26 |
문자열, 벡터와 배열 (0) | 2024.06.26 |
서론 (0) | 2024.06.24 |