Brise
[C++ 기본] 4. Variable 본문
// 4_변수1
#include <iostream>
// C++ 은 C언어의 변수 관련 문법을 더욱 발전시켰습니다.
struct Point
{
int x, y;
};
int main()
{
int n1 = 0b1; // 2진수 표기법, C++11 부터 지원
int n2 = 1'000'000; // digit separator, C++11부터
// 원리 : 정수형 리터럴 사이의 ' 는
// 컴파일러가 무시
struct Point p1; // C언어 스타일
Point p2; // C++언어 스타일.
//foo()
int n3; // 함수 중간에 변수 선언.
// C89 : error
// C99 : ok.
// C++ : ok.
}
C와 C++ 문법 기준이 개선되며 변수 선언 위치 및 방법이 크게 개선되었습니다.
컴파일러의 버전에 따라 선언위치, prefix, 리터럴 값의 가독성 증가를 위한 divider등을 추가할 수 있습니다.
또한 C언어에서 불필요하게 typedef struct ... {} ...와 같은 패턴을 사용하지 않아도 되도록 C++언어에서는 구조체 타입을 좀 더 편리하게 사용할 수 있도록 하였습니다.
// 4_변수1
#include <iostream>
struct Point
{
int x, y;
};
int main()
{
// 20page - 중요한 변화.!
//int n = 10;
//int x[3] = { 1,2,3 };
//Point p1 = { 1,2 };
// 일관된 초기화(uniform initialization) 문법 - C++11
// 모든 종류의 변수를 초기화 할때 {} 사용
// int n = { 10 };
// int x[3] = { 1,2,3 };
// Point p1 = { 1,2 };
int n { 10 };
int x[3] { 1,2,3 };
Point p1 { 1,2 };
// 직접 초기화(direct initialization) : =이 없는것
// 복사 초기화(copy initialization) : =이 있는것
// {} 로 초기화(직접 또는 복사)시 데이타 손실 발생하면 error.
int n2 = 3.4; // ok.. 하지만 나쁜 코드,
int n3 = { 3.4 }; // error. preventing narrow 라는 문법
char c = { 300 }; // error
}
C언어에서는 primitive type에 대한 값을 선언할 때 {}를 사용할 수 없었던 것과 달리 모든 변수선언에 대하여 {}를 사용할 수 있습니다.
하지만 이 경우 좀더 strict한 기준을 사용하게 되어 데이터 타입 변형을 통한 손실이 있을 경우 컴파일러 오류를 발생시킵니다. 이 때문에 런타임 이전에 발생할 수 있는 Human-error를 미리 확인할 수 있습니다.
#include <iostream>
struct Point
{
int x, y;
};
void foo(int n) {} // int n = {3}
void goo(Point pt) {}
int main()
{
foo(3);
foo({ 3 }); // int n = {3}
Point p = { 1,2 };
goo(p);
goo({ 1,2 }); // ok.. Point pt = {1,2}
}
C언어에서는 primitive type에 대해서만 리터럴을 선언할 수 있었지만(무명 변수)
C++언어에서는 구조체에 대해서도 리터럴을 선언할 수 있습니다.
int main()
{
int x[3] = { 1,2,3 };
//int n = x[0];
auto n = x[0]; // 우변의 표현식을 가지고 좌변의 타입 결정
// 컴파일러가 결정. 실행시 성능저하 없습니다.
// C++11
decltype(n) n2; // () 안의 표현식과 동일한 타입
// C++11
auto a1 = x; // a1의 타입은 ?
// 1. int a1[3] 2. int*
// int a1[3] = x; // error
// int* a1 = x; // ok
decltype(x) d1; // int d1[3]
decltype(x) d2 = x; // int d1[3] = x 이므로 error
// 22 page 제일 아래
//decltype(x[0]) d3; // error. d3 int&
}
auto와 decltype을 이용하여 좀 더 유연한 프로그래밍이 가능합니다. 또한 이 부분의 경우 컴파일 타임에 결졍되므로 실행 성능에는 문제가 없습니다만, 개발자가 해당 내용에 대하여 잘 파악하고 있지 않은 경우 오류가 발생할 가능성이 높습니다.
C++의 경우 &에 대하여 주소와 레퍼런스 2개의 값을 모두 사용할 수 있어 이 부분에 대한 주의가 필요합니다.
// typedef int DWORD;
// typedef void(*PF)();
// typedef : 타입에 대한 별칭(alias) 만들기
// using : 타입에 대한 별칭 + 템플릿 별칭 만들기
//
// C++11 using
using DWORD = int;
using PF = void(*)();
int main()
{
DWORD n; // int
PF f; // 함수 포인터
}
C에서 typedef를 이용한 것과 마찬가지로 C++에서는 using 키워드를 이용하여 변수 타입에 대한 별칭을 만들 수 있습니다. 추가로 template에 대한 별칭 또한 만들 수 있습니다.
// 4_변수6.cpp 25 page
struct Point
{
int x, y;
};
int main()
{
Point pt = { 1,2 };
int x = pt.x;
int y = pt.y;
// C++17. structure binding
// VC++ 2017, 2019 : 디폴트로 C++14까지 지원
// /std:c++17 또는 /std:c++latest
// g++ 8.x, 9.x : 디폴트로 C++14까지 지원
// -std=c++17
auto[a, b] = pt; // 반드시 auto 만 가능
int arr[3] = { 1,2,3 };
auto[a1, a2, a3] = arr; // ok
// 64 bit 타입
long long n3; // 64 bit 정수.
}
최근 C++ 문법의 경우 C언어에서는 지원되지 않은 구조체를 이용한 개별 변수의 초기화 기능(structure binding)을 지원합니다.
다만, 이 경우 auto의 선언이 강제됩니다.
'프로그램 > C,C++' 카테고리의 다른 글
[C++ 기본] 7. template function (0) | 2022.01.16 |
---|---|
[C++ 기본] 6. Function (0) | 2022.01.15 |
[C++ 기본] 5. constexpr (0) | 2022.01.15 |
[C++ 기본] 3. 입출력 (0) | 2022.01.14 |
[C++기본] 2. namespace (0) | 2022.01.14 |
[C++기본] 1. Hello world! (0) | 2022.01.14 |
VS Code에서 uint32_t 타입 오류로 표시되는 경우(임베디드, stm32) (0) | 2021.02.02 |