박가방

[C++] 리터럴 상수 (Literal Constant) 본문

프로그램 언어/C++

[C++] 리터럴 상수 (Literal Constant)

박가방 2022. 8. 7. 12:52

개인 공부 중입니다. 조언 환영합니다.

1.서론

- 상수(constant)란 직접 코드에 삽입된 값.

- 상수는 변수와 달리 프로그램이 실행되는 동안 메모리에 저장된 데이터를 변경할 수 없다.

변수) 하나의 특정 값을 저장할 수 있는 메모리 공간 (특정 값이란 숫자, 문자,논리, 배열 등  하나의 데이터이다.) 

int x = 25;

- 변수 x라는 값에 상수 25를 대입한다

- 25 라는 값에 30을 대입(25=30)할 수 없다. -> 상수

 

 

 

표 1.1 상수의 종류

숫자 상수 정수 상수 -65536, -50, 0 ,10 등
실수 상수 3.141592, 15.6, 44.56 등
문자 상수 문자 상수 'a'~'z', '!', '@' 등
문자열 상수 'Korea', 'Hello', '대한민국' 등
논리 상수 true 또는 0이 아닌 수
거짓 false 또는 0

 

2. 표현방식에 따른 상수

C++에는 두 가지 상수가 존재한다. 

- 리터럴 상수 (literal constant)

- 심볼릭 상수 (symbolic constant)

 

3. 리터럴 상수(literal constant)

- 리터럴 상수는 변수와 같이 자료형 타입(실수, 정수, 문자)을 갖는다.

- 그러나 변수와 달리 저장된 메모리 공간을 가리키는 이름을 가지지 않는다.

 

  3.1 논리형(bool) 정수형(integer) 실수형(float) 리터럴

#include <iostream>

int main() {
    using namespace std;
    /*부울 리터럴*/
    bool Weather = true;     // Weather는 bool literal true가 할당.
    
    /*정수 리터럴*/
    int x = 1;               // 정수 변수 'x'는 literal 5가 할당.
    cout << 1 * 2 << endl;     // 1와 2는 정수 리터럴
    
    /*실수 리터럴*/
    float pi = 3.141592f;   // 3.14159s flaot literal
    float le_pi = 0.628e1;  // 0.628*10^1
    float lee_pi = 628e-2;  // 628*10^-2
    cout << pi<<endl;
    cout << le_pi << endl;
    cout << lee_pi << endl;
}

- 숫자 리터럴의 경우 유형을 결정하는 접미사가 포함된다.

- 이를 생략할 경우 컴파일러는 의도하는 것이 어떤 종류의 상수인지 유추한다. (정수형의 경우 int, 실수형의 경우 float)

- 접미사를 통해 해당 상수의 타입을 명시할 수 있다.

 

 

표3.1. 접미사를 통해 나타낼 수 있는 정수형 및 실수형 타입

접미사(suffix) 타입(type)
정수형 기본 설정 int
u or U usigned int
l or L (singed) long
ul, uL, Ul, UL, lu, lU, Lu, or LU unsigned long
ll or LL (signed) long long
ull, uLL, Ull, ULL, llu, llU, LLu, or LLU unsigned long long
실수형 기본 설정 double
f or F float
l or L long double

 

# 그러나 접미사를 사용하여 명시하는 것 보다 캐스팅 사용하는 것이 읽기 편하다.

float pi = 3.14f;    //3.14가 캐스팅 되어 pi에 대입
long n2=5l;
double d= 6.0e10;
//명시해주기위한 용도로 사용되나, 차라리 캐스팅을 사용하는 것이 나음

/*Casting*/
int i = (unsinged int)1234; // 이럴 경우 프로그래머가 읽기 편함

 

 

  3.2 10진수(decimal) 8진수(octal) 16진수(hexadecimal) 리터럴

    3.2.1 각 진수 표현으로 나타낸 결과

    3.2.2 cout 객체에 dec,hex,oct 조정자를 전달한 결과.

#include <iostream>

int main() {
    using namespace std;
    int a = 12;
    int oct_a = 012;			//8진수는 숫자앞에 0,   1*(8^1)  + 2 = 10    
    int bin_a = 0b00010010;		//2진수는 숫자앞에 0b   1*(2^4)  + 1*(2^1) = 18
    int hex_a = 0x12;			//16진수는 숫자앞에 0x, 1*(16^1) + 2 = 18
    
	/*3.2.1 각 진수 표현으로 나타낸 결과*/
    cout << "12 : "   << a     << endl;
    cout << "012 : "  << oct_a << endl;
    cout << "0b00010010 : " << bin_a << endl;
    cout << "0x12 : " << hex_a << endl;

	/*3.2.2 cout 객체에 dec,hex,oct 조정자를 전달한 결과.*/
    cout <<"숫자 12를 10진수로 " << a << endl;
    cout << oct;
    cout << "숫자 12를 8진수로 " << a << endl;
    cout << hex;
    cout << "숫자 12를 16진수로 " << a << endl;
}
결과

12  : 12
012 : 10
0b00010010 : 18
0x12 : 18

숫자 12를 10진수로 12
숫자 12를 8진수로 14
숫자 12를 16진수로 c

 

표 3.2. 각 진법의 출력 형태

10진법 0 1 2 3 4 5 6 7 8 9 10 11
8진법 0 1 2 3 4 5 6 7 10 11 12 13
16진법 0 1 2 3 4 5 6 7 8 9 A B

 

- 실수로 0을 붙였다가 8진수가 되는 케이스가 있으므로 주의하자

- 16진수를 프로그래머들이 많이 사용하는 이유는 0011 1010 1111 ... 처럼 이진수가 반복되면 읽기 힘든데

   3A7F로 바꾸면 읽기가 훨씬 편하다

 

 

4 심볼릭 상수(Symbolic constant) [Reference 2번]

- 심볼릭 상수는 변수와 같이 문자로된 이름을 가지는 상수이다.

- 심볼릭 상수는 반드시 선언과 동시에 초기화를 해야한다

- 심볼릭 상수는 매크로(define)와 const 키워드를 사용하여 선언 가능하나,

                   매크로는 C언어의 문법으로, C++에서는 가급적 const 키워드를 사용하여 선언한다.

/*const 상수*/
const int Age = 10;
/*define 상수*/
#define MAX_STUDENT 30

- define은 상수를 만드는게 아니라 문자열을 치환하는 전처리기이다. 단지 MAX_STUDENT를 30으로 치환하는 개념.

 

  4.1 매크로를 이용한 선언보다 const 키워드를 사용한 심볼릭 함수의 장점으로는

    -  매크로는 직접 가서 봐야하기 때문에 디버깅이 힘들다. (쉽게배우는 C언어 강의 중, 무슨말인지 모르겠음.)

    -  define은 cpp file에서 전처리기 역할로 인해 위치가 main 바깥에 있어, 영향을 끼치는 범위가 넓어 좋지 않다.

    - 상수의 타입을 명시적으로 지정할 수 있다.

    - 구조체와 같은 복잡한 사용자 정의 타입에도 사용할 수 있다.

    - 해당 심볼릭 상수를 특정 함수나 파일에서나 사용할 수 있도록 제한이 가능하다.(함수나, 파일 내에서만 사용가능)

 

TMI

- 매크로는 대문자로 많이 사용한다

- const는 물리함수에서 ceff_,  k_로 사용하기도 한다.

- 만약 const price_per_item이 변수가 되려면 const만 풀어놓으면 되므로 관리하기 편하다.

 

 

4.2 심볼릭 상수의 사용법

   4.2.1 변수 선언 시

	const double gravity{ 9.8 }; 
    // const -> 내 코드 바꾸지마 
    // const는 반드시 선언과 동시에 initial 해줘야함. 
    
	gravity =1.2;                 //오류뜸. 절대 이런 방식으로 변경하지 말 것.
	//어떠한 경우에도 변해야하는 게임을 만들어야한다면 주석을 달거나 다른 기법을 사용.
    
	// 참고 : double const gravity {9.8} 도 가능하지만, 일반적으로 const는 앞에 붙임

 

 

 

    4.2.2 함수 사용 시

void printNumber(const int my_number) //const로 파라미터를 변경하지 않도록 막음.
{
	cout << my_number << endl;
}

int main()
{
	printNumber(123);
}

    - 함수의 작동 형태는 123이란 argument가 printNubmer 함수로 전달되는 과정에서

      함수의 영역( 중괄호{} )안에서 int my_number라는 것이 선언되고 123이 들어가는 형태.


    - 따라서 my_number라는 파라미터는 printNumber의 입력이다.

      이를 내부에서 파라미터를 변경하는 것은 코드 설계상 매우 좋지 않으므로 const로 막아버린다.

 

 

4.3 의미적인 차이

    const int my_const(123);         //의미적으로는 컴파일 타임 상수
    				    //컴파일 시 반드시 지정되는 값.
	
	int number;
	cin >> number;
	const int special_number(number); //변수로 상수를 초기화, 의미적으로 런타임 상수
					  //런타임 시 지정되는 값.


	// 이두개를 잘 분리해서 해석하기위해 cpp11버전부터
	constexpr int my_const1(123); // constexpression -> 컴파일 타임 상수.

- 의미적으로 컴파일 시 지정되는 데이터가 있고, 런타임 시 지정되는 데이터가 있다. 이 둘을 분리하기 위해  C++11버전부터는 Constexpr를 통해 분리한다.

 

 

 

4.4 symbolic 상수의 헤더파일 선언

/*CONSTANT.h file*/

#pragma once

namespace constants
{
	constexpr double pi(3.141592);
	constexpr double avogardo(6.0221413e23);
	constexpr double moon_gravity(9.8 / 6.0);
	//...

}
/*main.cpp*/
#include <iostream>
#include "CONSTANT.h"

using namespace std;

int main(){
	double radius;
	cin >> radius;
	double circumference = 2.0 * radius * constants::pi;
	
}

- 위와 같이 CONSTANT를 따로 지정하여 관리할 경우 용이하다.

 

 

 

 

5. 바이너리코드의 single quote 사용시 장점

- 컴파일러가 single quote를 무시하므로 가시적으로 좋다.

	int x= 0b1010'1111'1000; // '붙으면 컴파일러가 무시하므로. 프로그래머 입장에서 읽기 편함.
	cout <<x<< endl;         // 10진수도 (', single quote)를 쓸 수 있음.

 

 

6.매직넘버(Magic Numbers)

# 나쁜 예

	/*나쁜 예*/
    int num_items=1;
	int price = num_items * 10;     // 10 is ~~something

위 코드에서 10 숫자를 매직넘버라고 부른다.

이는 콘텍스트(context,주석 2)가 없는, 코드 중간에서 하드코딩된 리터럴을 말한다.

- 주석이 없는 경우 추론하기 매우 어렵다.

- 주석이 있는 경우에도 반복 사용될 경우, 수정해야할 경우(price가격에 곱한 상수 10이 -> 30으로 변경될 시) 문제를 해결하기 어렵다.

 

# 좋은 예

	/*좋은 예*/
	const int price_per_item = 10;
	int price2 = num_items * price_per_item;

- 귀찮더라도 특정 상수를 변수에 대입하여 코딩하자.

 

 2 ) 정보통신 용어로서의 컨텍스트는 호출, 응답 간의 환경 정보라고 정의할 수 있을 것 같다. 즉, 누가 무엇을 어떤 의도를 가지고 언제 행위를 하였는지에 대한 정보를 통칭하여 컨텍스트라고 하는 듯 하다. [Reference 6]

 

 

 

Reference
1: https://boycoding.tistory.com/155
2: http://www.tcpschool.com/cpp/cpp_datatype_constant
3: https://digiconfactory.tistory.com/entry/C-%EC%83%81%EC%88%98-%EB%A6%AC%ED%84%B0%EB%9F%B4-%EC%83%81%EC%88%98%EC%99%80-%EC%8B%AC%EB%B3%BC%EB%A6%AD-%EC%83%81%EC%88%98
4: https://opentutorials.org/module/3921/23508
5. 따라 배우는 C++ - 홍정모
6. https://m.blog.naver.com/ljhsecret/60155604088

 

'프로그램 언어 > C++' 카테고리의 다른 글

[C++] Expression(표현식)과 Statement(명령문) 차이  (0) 2022.08.07
[C++] 함수  (0) 2022.08.07