본문 바로가기
기계공학부 시절의 기록/C++일기

상수 : 리터럴상수, 심볼릭상수

by juhyeonglee 2021. 5. 7.
728x90
반응형

 

 

제가 빠르게 복기하기 좋게 정리한 글입니다. 파일을 추가하는 세세한 방법과 과정은 마지막에 첨부된 영상으로 확인하시면 좋을 것 같습니다 :) 강의목차의 번호와 같은  목차번호를 사용하고 있으니 참고하세요!

 


 

상수란 프로그램 실행 중에 계산으로 사용할 값정도 생각하면 될 것 같다.

리터럴 상수와 심볼릭 상수가 있는데 리터럴 상수는 데이터를 그대로 쓰는 것이라면 심볼릭 상수는 데이터에 이름을 지어 그 이름으로 상수를 사용하는 것이다.

 

 

 

1. 리터럴 상수

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
int main()
{
    // 아래처럼 특정 자료형임을 강조하기 위해서 
    // 뒷부분에 추가처리를 하는 경우도 있다.
    float f = 3.14f;
    unsigned int n = 5u;
    long n2 = 5L;
    double d = 6.0e-10;
 
    return 0;
}
cs

 

여러 진수로 입력하기

코딩을 하다보면 10진수보다 2진수로 하는 것이 더 나을 때가 있고 2진수보다는 16진수가 더 편할 때가 있다고 한다.

그리고 수가 너무 길어지다보면 사람 입장에서 '를 이용해 몇자리단위로 끊어 구분하는 것이 좋을 수 있는데 숫자 중간중간의 '는 컴파일러가 무시해 잘 활용할 수 있다고 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
 
int main()
{
    using namespace std;
    // 10진수(Decimal) : 0 1 2 3 4 5 6 7 8 9 10
    // 8진수(Octal)    : 0 1 2 3 4 5 6 7 8 10 11 12 13
    // 16진수(Hexa)    : 0 1 2 3 4 5 6 7 8 9 A B C D E F 10
    
    // 10진수
    int x = 12;
    cout << x << endl;
 
    // 8진수 : 0을 앞에 붙인다.
    x = 012;
    cout << x << endl;
 
    // 16진수 : 0x를 앞에 붙인다.
    x = 0xF;
    cout << x << endl;
 
    // 2진수 : 0b를 앞에 붙인다.
    x = 0b100101010;
    cout << x << endl;
 
    // 수가 길어질 때 중간중간 '를 넣어도 컴파일러는 무시한다.
    x = 0b100'101'010;
    cout << x << endl;
 
    //입력을 어떤 진수로 해도 출력은 10진수로 된다.
 
    return 0;
}
cs

 

이렇게 세세한 팁들은 실제 잘 안쓸 수 있지만 다른 사람의 코드에서 종종 나타난다. 코딩을 공부하는 목적 중에 다른 사람의 오픈소스코드를 활용할 때, 코드를 이해할 때 필요하기 때문이다.

 

 

2. 심볼릭 상수

직관적으로 이해할 수 없는 상수에 이름을 지어 코드이해도를 높이는 것이 심볼릭 상수이다.

 

magic넘버 : 직관적으로 이해할 수 없는 상수

아래처럼 식에 10이 있지만 왜 10이 곱해지는지 이해할 수 없는 경우가 있다. 이러한 상수를 magic넘버라고 한다. 주석을 다는 방법이 있지만 그 수가 많을 때는 자칫 코드가 지저분해질 수 도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
int main()
{
    using namespace std;
    
    int num_items = 123;
    int price = num_items * 10;
    // 10이 왜 저 식에 있는지 설명하기 위해서 주석을 달 수도 있지만
    // 눈에 잘들어오지 않는 경우가 대부분이다.
 
    return 0;
}
 
cs

이러한 상수도 이름을 지어버릴 수 있다. 그러면 식을 보고 10은 왜??라며 의문을 갖지 않을 것이다. 

 

 

const

const를 사용하면 이 후 코드에서 해당 변수를 다른 상수로 바꾸는 것을 불가하게 한다.

아래 코드에서 정한 price_per_item에는 다른 값을 넣을 수 없다. (특별히 뱌꾸는 방법이 있지만 전혀 추천하지 않는다고 한다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
int main()
{
    using namespace std;
    
    const int price_per_item = 10;
 
    int num_items = 123;
    int price = num_items * price_per_item;
 
    return 0;
}
 
cs

 

 

1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
int main()
{
    using namespace std;
 
    const double gravity{ 9.81 };
 
    return 0;
}
cs

 

 

함수의 파라미터에 const를 넣는 이유와 의미

const를 함수에서도 쓰는 경우가 있다.

함수의 입력을 굳이 건드리는 경우가 없다. 굳이 바꾸었을 때 혼란을 만들 수 있기 때문에 함수 입력값을 const로 고정시켜버리는 경우가 많다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
using namespace std;
 
// const는 함수 파라미터에도 많이 쓰인다.
void printNumber(const int my_number)
{
    //굳이 바꾸고 싶다면 아래처럼 직접 바꾼다.
    int n = my_number;
    cout << n << endl;
}
 
int main()
{    
    printNumber(123);
    const double gravity{ 9.81 };
 
    return 0;
}
cs

 

 

컴파일 타임과 런타임

컴파일 타임 : 아래 코드를 보면 변수 초기화를 함과 동시에 const지정을 하는 문장이 있고 (7, 11 명령문)

런타임 : 입력을 받아 프로그램을 실행 중에 상수를 받아 const지정이 되는 문장이 있다. (17 명령문)

이 두 문장의 차이는 컴파일 타임과 러닝 타임에 const지정이 된다는 것이다. 사소하고 오묘한 차이이지만 전문가는 디테일을 알아야 한다.

 

cpp 11에서부터 문법을 통해서 컴파일타임 상수인지 런타임 상수인지 구별하기 위해 constexpr를 내놓았다.

constexpr는 컴파일 타임, 이미 타이핑을 통해서 지정된 상수임을 의미한다.

이를 런타임 상수에서 사용하면 에러가 발생한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
using namespace std;
 
int main()
{    
    // 컴파일 타임에서 결정되는 const int 변수
    const int my_const(123);
    
    // 컴파일 타임에서 결정되는 const 변수를 따로 구분하기 위해서
    constexpr int my_consts(123);
    
    int num;
    cin >> num;
 
    // 런타임에서 결정되는 const int
    const int spectial_number(num);
    return 0;
}
 
cs

 

 

 

const상수가 너무 많을 때

다뤄야 할 상수가 많을 때는 따로 헤더파일을 만들고 그 안에 상수들을 이름공간에 정리해 쓴다.

그렇지 않으면 본문 코드가 지저분해지고 가독성이 떨어질 수 있기 때문이다.

 

(헤더파일)

1
2
3
4
5
6
7
8
9
#pragma once
 
namespace constants
{
    constexpr double pi(3.141592);
    constexpr double avogadro(6.0123123);
    constexpr double moon_gravity(9.8 / 6.0);
    // ...
}
cs

 

본문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include "My_constants.h"
 
using namespace std;
 
int main()
{    
    double radius;
    cin >> radius;
 
    double circumference = 2.0 * radius * constants::pi;
    cout << circumference << endl;
 
    return 0;
}
 
cs

 

이렇게 본문에 활용할 상수들을 따로 헤더파일로 관리하면 후에 어떤 상수를 고쳐야할 때, 본문에서 상수위치를 찾느라 헤매지 않고 헤더파일로 들어가 해당 상수를 보다 쉽게 찾아 고치면 코드 전체의 상수에 적용된다.

 

 

 

출처)

홍정모의 따배씨++

 

www.youtube.com/playlist?list=PLNfg4W25Tapw5Yx4yuExHNybBIUk68aNz

 

[따배씨++] 따라하며 배우는 C++ | 모던 c++, c++ 강의, c++ 강좌, c++ 언어, 기초 프로그래밍, c++ 프로그

[홍정모의 따라하며 배우는 C++ (모던 C++)] https://www.inflearn.com/course/following-c-plus?inst=aa88a07c [홍정모의 따라하며 배우는 C언어] https://www.inflearn.com/course/following-c?i...

www.youtube.com

좋은 강의에 너무나 감사하다.

이전에는 그냥 무작정 따라썼던 코드들을 한줄한줄 이해하며 공부할 수 있다.

언젠가 어느 언어든 자신감이 있는 코드마스터가 될 것이다.

 

데이터가 인간을 대신해 일을 하게하고

데이터를 제어해 로봇을 제어하고 싶다.

 

'아앙의 전설'에서 주인공은 물/불/흙/공기 원소를 자유자재로 다룬다.

수많은 데이터가 넘실대는 현대에서는 데이터를 자유자재로 다루는 프로그래머.

실력있는 프로그래머가 되기 위해서는 코드 한줄이 내부적으로 어떻게 작동되는지를 이해해야한다.

 

 

728x90
반응형

댓글