1-0

새로운 함수를 만들 때 전달받을 값이 있다면 매개변수를 선언해주는데 

그 매개변수에 기본값을 1-0 이미지처럼 설정해 줄 수 있다. 

즉 함수를 호출할 때마다 값을 전달해주는 것이 아니라 함수 선언할 때 매개변수에 직접

기본값을 지정해줄 수 있다. 이렇게 하면 1-0 이미지처럼 함수를 호출할 때 기본값이 설정되어 있는 부분은

값을 전달할 필요가 없어진다.

 

주의할 점은 이 기본값을 지정해주는 매개변수는 제일 뒤쪽에 있어야 한다. 다른 매개변수 사이에 있으면

에러가 발생한다.

 

1-1

기본값은 기본적으로 제일 뒤쪽에 있어야 하며 

1-1 이미지처럼 그 후로는 계속해서 기본값을 추가할 수 있다.

 


 

오버 로딩이란?

함수 이름의 중복 사용을 말한다. 

함수 이름을 중복 사용하기 위한 조건이 두 가지가 있다.

 

1. 매개변수 개수가 달라야 한다

2. 매개변수 타입이 달라야 한다. (순서가 다른 걸 포함한다)

 

매개변수 갯수가 다른 경우

 

매개변수 타입이 다른 경우

 

1-0

어셈블리 공부할 때 나왔었던 스택 메모리에 관해 다시 한번 복습해보려고 한다.

 

함수가 호출되면 각 함수는 스택이라는 저장 공간에 [매개변수] [RET] [지역변수] 공간을 할당받는다.

함수 내에서 다시 함수가 호출되면 위에 이미지처럼 높은 주소에서 낮은 주소 순서로 공간을 할당받는다.

이 할당된 공간들은 함수가 종료되면 사라진다. 중요한 개념이니 잘 기억해두자.


2-0

코드가 위와 같을 때 첫 번째 hp와 두 번째 hp는 각각 어떤 값이 출력될까?

 

2-1

정답은 1, 1이 출력된다.

그 이유는 무엇일까? 분명 코드에서는 출력문 사이에 함수를 호출해서 hp + 1을 해줬으니 

2가 출력돼야 하는 게 정상 아닐까?

 

이렇게 출력되는 이유는 이미 맨 위에 적어놨었다. 

즉, 함수가 호출되고 저장되는 공간이 다르다는 것이 중요한 포인트이다.

 

우선 main 함수에서 int hp 명령을 이용해 '지역 변수'를 선언한다. 

지역 변수는 main 함수가 할당된 스택 저장 공간에서 지역 변수 부분에 저장된다.

 

그리고 출력문 하나를 출력하고 a라는 함수가 호출된다. a라는 함수는 매개 값으로 hp(==1)를 할당받는다.

a라는 함수가 호출되었으니 a 함수 쪽으로 시선을 돌리면 int hp라는 명령을 이용해 '매개 변수'를 선언한다.

매개 변수는 a 함수가 할당된 스택 저장 공간에서 매개 변수 부분에 저장된다.

 

즉, 두 변수는 전혀 다른 공간에 저장된 다른 변수이다.

a 함수 내에서 hp = hp + 1이라는 명령은 매개 변수로써 선언된 hp 변수의 값을 변경시키는 것이지

main 함수 내에 있는 지역 변수 hp를 변경시키는 것이 아니다.

 

또한 중요한 것이 해당 함수에 할당된 저장 공간은 해당 함수가 종료되면 그대로 사라진다.

즉, a 함수 내에서 지역 변수를 선언하거나 매개 변수를 이용해 값을 변경하더라도

a 함수가 호출이 끝나면 저장 공간에서 사라진다는 것이다.

 

그렇기 때문에 main 함수 내에 지역 변수 hp는 어떠한 변경점도 없이 그대로 두 번 출력되는 것이다.


아래 내용은 스택 프레임과 관련이 없고 필자의 궁금증에 의해 실험해보았다.

이미지 2-0 코드에서 a 함수가 값을 출력하기 위해 void를 삭제하고 int를 넣어주었다.

그리고 리턴 값을 매개 변수 hp로 설정해주었다.

 

지금까지 설명했듯이 함수가 종료되면 해당 함수에 할당된 저장 공간들도 사라지기 때문에 

매개 변수 hp는 사라질 것이다. 하지만 리턴을 해주게 되면 어떻게 될지 궁금해서 실험해보았지만 

결괏값에 변화는 없었다. 그럼 리턴 값은 어디로 간 것일까?

 

이번에는 a 함수 호출을 출력문 사이가 아닌 마지막 출력문에 직접적으로 넣어봤다.

이번에는 원하던 값이 출력되는 것을 확인했다.

즉, a 함수의 리턴값 hp는 a 함수가 호출된 라인에서만 살아있고 함수 호출이 종료되는 다음 라인에서는

저장 공간이 사라지듯이 리턴 값도 사라진다.

열거형이란?

어떤 값들을 순서대로 나열해놨다고 해서 열거형이라고 불린다.

C++ 언어에서는 enum [명칭]과 같이 사용자가 직접 정의해서 사용할 수 있다. 

 

1-0 열거형 코드

 

1-0 이미지의 주석에서도 설명했듯이 따로 숫자를 지정하지 않으면 첫 번째 값은 0으로 설정되고

그 이후 값들은 순서대로 +1 값을 가지게 된다. 

 

각각의 값들마다 원하는 정수를 지정해 줄 수 있다.

 

그렇다면 열거형은 왜 사용하는 것일까?

주된 이유는 가독성과 효율성 때문이다.

 

시스템적인 측면에서 보자면 열거형의 값들은 메모리에 올라가지 않는다. 

그렇기 때문에 각각의 값들을 int타입으로 선언했을 때보다 효율적으로 사용할 수 있다. 

 

그리고 프로그래머 입장에서 볼 때는 어떤 한 사람이 코드를 제작하는 것이 아닌

회사나 단체로 커다란 코딩을 한다고 가정하면 가독성적인 측면에서 아주 유용하다.

예를 들어 다른 사람이 작성한 코드를 이해하거나 예전에 작성한 코드를 수정할 때 

열거형을 사용하면 직관적인 문자열로 인해 코드를 파악하기 쉬워진다.


추가적으로 열거형과 비슷한 개념으로 사용할 수 있는 #define에 대해서 알아보자

#define은 #이 붙어있으므로 전처리 지시문이다.

 

전처리 지시문이란? 일반적으로 소스 프로그램을 쉽게 변경하고 여러 실행 환경에서 

쉽게 컴파일할 수 있도록 하기 위해 사용된다. 즉, 컴파일 이전의 선행 처리 같은 개념이다.

 

그럼 이 #define은 어떤 기능을 하는 것인가?

 

2-0

 

#define [명칭] [사용자 정의 값]

이런식으로 정의를 하고 메인 함수 내에서 실제로 사용할 때는

[명칭] 이후에 사용자가 직접 정의한 값이 그대로 [명칭]에 대체된다. 

 

예를 들어 2-0처럼 정의했다고 가정하자

메인 함수 내에 정의한 define을 사용하려고 [명칭]을 가져온다

 

TEST;

AAAA;

 

이런 식으로 가져오면 사전에 정의한 [사용자 정의 값]이 그대로 대체되기 때문에 

 

cout << "Hello World" << endl;
11111+22222

 

이것과 같다.

 

주의할 점은 #define에서 선언한 사용자 정의 값은 적힌 그대로 가져오기 때문에 사용 시 불편함을

유발할 수 있으며 디버깅하거나 코드를 수정할 때도 해당 define의 사용자 정의 값을 찾기 어렵기 때문에

대부분의 C++ 프로그래머들은 사용을 지양하고 있다.

 

 

별 찍어내기

 

1-0 코드

사용자로부터 정수를 입력받아 n x n 별(*)을 찍어내는 코드


2-0 코드

사용자로부터 정수를 입력받고

해당 정수의 크기만큼 순차적으로 별의 숫자가 늘어나는 코드이다.

 

2-1 결과


3-0 코드

사용자로부터 정수를 입력받고

해당 정수의 크기만큼 역순으로 별을 출력하는 코드

 

3-1 결과


4-0 코드

2단부터 9단까지 차례대로 구구단을 출력하는 코드

 

4-1 결과

 

9단까지 잘 출력되지만 길어서 패스


가위 바위 보 구현하기

 

5-0
5-1
5-2
5-3
5-4 결과

 

승률을 구할 때 비긴 것은 제외시켰다.

'프로그래밍 언어 공부 > C++' 카테고리의 다른 글

함수와 스택 프레임  (0) 2022.05.27
열거형  (0) 2022.05.26
const와 메모리 구조  (0) 2022.05.23
비트 플래그  (0) 2022.05.22
불리언, 부동소수점, 문자, 문자열  (0) 2022.05.20

const

 

이전 비트 플래그를 공부할 때의 코드를 잠시 살펴보면

 

0b0000 [무적][공포][기절][탈진]

 

무적 상태로 만드는 경우

flag = (1 << 3); 

 

무적+공포 상태로 만드는 경우

flag |=(1 << 2);  // | 비트 or 연산

 

위와 같이 코드를 작성했었는데 문제가 하나 있다.

소스코드에 직접적으로 값을 지정해서 코드를 짜면(하드코딩이라고 표현함) 

유연성이 없고 확장성이 낮기 때문에 나중에 수정하거나 특정 상황이 발생했을 때

대응하기가 힘들다.

 

그래서 직접적으로 값을 넣어주는 것이 아닌 값 자체를 하나의 상수 값으로 만들어주는 것이 좋다.

한 번 정해지면 바뀌지 않는 값들을 상수라고 하는데 이것을 영어로 constant라고 한다.

프로그래밍에서는 constant의 약자인 const를 붙여서 변수를 상수화한다.

const를 붙였다면 초기값을 반드시 지정해야 한다는 것도 알아두자.

 

1-0 const 실습

위 이미지와 같이 const를 이용해 변수를 상수화 시켜주면 

다른 누군가가 a~d까지의 값을 실수로 변경해도 프로그램상 에러가 뜨며 값이 바뀌지 않으며,

해당 상수값들을 변경하거나 추가할 때는 const로 선언해준 부분에 값을 바꾸거나 추가해줌으로써

메인 함수 내에 있는 코드를 직접적으로 수정하지 않아도 원하는 결과를 얻을 수 있게 되므로 

효율적이고 좋은 코드라고 할 수 있다.


메모리 구조

 

이미지 1-0에서 보이듯이 메인 함수 밖에서 선언한 변수들은 '전역 변수'라고 한다.

그리고 메인 함수 안에서 선언한 변수들은 '지역 변수'라고 부른다.

전역 변수와 지역 변수의 근본적인 차이점은 변수가 저장되는 공간이다.

 

함수 밖에서 선언된 변수는 데이터 영역에 할당된다.

section .data (초기값이 있는 변수)

section. bss (초기값이 없는 변수)

section. rodata (읽기 전용 데이터)

위와 같이 함수 밖에서 전역 변수로써 선언된 변수들은 데이터 영역에 할당된다.

여러 함수가 호출되어도 데이터 영역에 할당되었기 때문에 어디서든 사용이 가능하다.

그리고 함수가 종료되어도 해당 변수는 유효하다.

 

지역 변수는 스택 영역에 할당된다.

특정 함수가 호출되면 스택 영역을 사용해 일시적으로 데이터를 저장하게 되고

해당 함수가 유효할 때만 그 데이터를 사용할 수 있다. 호출된 함수가 사용이 종료되면 

스택 영역은 반환되고 그 안에서 선언했었던 데이터 또한 사라지게 된다.

'프로그래밍 언어 공부 > C++' 카테고리의 다른 글

열거형  (0) 2022.05.26
분기문, 반복문을 활용해 코딩 연습하기  (0) 2022.05.25
비트 플래그  (0) 2022.05.22
불리언, 부동소수점, 문자, 문자열  (0) 2022.05.20
환경설정, 정수  (0) 2022.05.19

비트 플래그

 

비트 플래그는 저장공간을 좀 더 효율적으로 사용하기 위해서 사용한다.

1바이트는 비트가 8개인데 비트 플래그는 8가지 '상태'를 저장해서 사용할 수 있다.

하지만 bool타입은 8비트 중 1비트만 사용하고 나머지 7비트를 낭비함으로써

1가지 상태를 저장하기 때문에 비효율적이다. 이것이 특정 상황에서 bool 타입 대신 

비트 플래그를 사용하는 이유이다.

 

예를 들어

0b0000 [무적][공포][기절][탈진] 

이런 식으로 각 비트마다 사용자가 특별한 의미를 부여하고 해당 비트가

활성화되어있느냐를 따져서 부여한 의미가 발동하거나 발동하지 않게 할 수 있는 것이다.

 

0b0001 이 경우 마지막 비트가 활성화되어 있기 때문에 탈진 상태가 되는 것이다.

0b0011 이 경우 첫 번째와 두 번째 비트가 활성화되어 있기 때문에 기절과 탈진 상태가 되는 것이다.

 

무적 상태로 만드는 경우

flag = (1 << 3); 

 

무적+공포 상태로 만드는 경우

flag |=(1 << 2);  // | 비트 or 연산

 

이때 특정 자리의 비트가 활성화되어있는지 확인하고 싶다면?

bitmask를 활용할 수 있다.

지금 flag의 상태가 무적 상태인지 궁금하고 다른 상태는 관심이 없다고 가정해보겠다.

 

bool a =((flag & (1 << 3)) != 0)

이것을 비트단위로 자세히 보면

0b1100 (flag)

0b1000 (1 << 3)

이 둘을 and 연산해서 나온 값이 0과 다르다면 참

0과 같다면 거짓 상태를 bool 타입 변수 a에 저장한다.

 

이것을 통해 특정 상태가 활성화되어 있는지 확인할 수 있고 이 방법의 장점 중 하나는

확인하고 싶은 상태만을 1로 만들어서 and 연산하기 때문에 다른 자리의 상태들은

모두 0으로 처리된다는 것이다.

 

 

'프로그래밍 언어 공부 > C++' 카테고리의 다른 글

열거형  (0) 2022.05.26
분기문, 반복문을 활용해 코딩 연습하기  (0) 2022.05.25
const와 메모리 구조  (0) 2022.05.23
불리언, 부동소수점, 문자, 문자열  (0) 2022.05.20
환경설정, 정수  (0) 2022.05.19

불리언

 

bool타입은 참과 거짓을 나타내는 1바이트 정수이다. 

일반적으로 참과 거짓을 정수를 사용하지 않고 bool타입을 사용하는 이유는

가독성적인 이유가 크다. 

 

bool타입만 봐도 이것이 참과 거짓 둘 중 하나라는 것을 바로 알 수 있기 때문에

가독성적인 측면에서 bool타입을 사용한다.

 

C++ 선언 시 아래와 같은 형식을 사용한다.

bool [변수 이름] = [true or false];


부동소수점

 

부동소수점은 쉽게 말해 실수를 말한다.

부동소수점이란 단어만 보고 소수점이 고정된 상태를 상상하기 쉬운데 사실 정반대이다.

즉, 소수점을 유동적으로 움직여서 실수를 표현하는 방법이 부동소수점이다.

소수점을 유동적으로 움직여야만 하는 이유는 실수를 컴퓨터에서 효율적으로 표현하기 위해서이다.

 

예를 들어 3.141592와 같은 파이값이 있다고 하면

10진수를 기준으로 정규화를 시켜준다고 생각하면 0.3141592 * 10 이렇게 된다.

(실제로 컴퓨터에선 2진수로 변환해서 정규화가 진행된다)

정규화된 값을 3141592(유효숫자) 1(지수)로 구분한다.

 

C++에서 실수를 표현하는 타입은 총 두 가지인데 float, double이 있다. 

이 비트단위로 자세히 표현하면 아래와 같다.

float : 부호(1비트), 지수(8비트), 유효숫자(23비트) -> 총합 32비트 = 4바이트

double : 부호(1비트), 지수(11비트), 유효숫자(52비트) -> 총합 64비트 = 8바이트

이렇게 실수를 정규화시켜주고 해당 유효숫자와 지수를 통해 표현한다.

 

참고로 C++에서 float 타입에 실수를 저장할 때는 아래와 같이 선언한다.

float [변수명] = [실수값f];

 - ex) float a = 0.4f;  -> 기본적으로 실수 값을 저장하면 float 타입이라고 선언해도 double로 저장된다. 그렇기 때문에 실수 값 뒤에 f를 붙여서 float로 저장하겠다는 뜻이다.

 

double은 그냥 저장하면 된다.

double [변수명] = [실수 값];

 

부동소수점은 위와 같이 정수에 비해 복잡하고 까다로운데 

기억해야 할 가장 중요한 요소는 항상 '근사값'이라는 점이다.

즉, 정확하게 해당 실수를 표현할 수 없다. 최대한 근사한 값을 표현할 뿐이다.

특히 수가 커질수록 오차 범위도 기하급수적으로 커진다.


문자

 

C++에서 아래와 같은 타입으로 문자를 표현한다.

char : 알파벳, 숫자, 문자를 나타낸다.

wchar_t : 유니코드 문자를 나타낸다.

 

char ch = 'a';  // '문자'의 의미로 작은따옴표 '' 사용

char ch1 = '1'; // 1이라는 숫자가 아닌 문자가 저장됨

char ch2 = 'a' + 1;  // 결과는 문자 b가 출력된다.

 

위에 각 문자들은 고유의 숫자를 가지고 있으며 이를 표준으로 정의한 것이 

아스키코드표이다. ASCII(American Standard Code for Information Interchange)

 

하지만 국제화 시대에 영어만으로 서비스하는 데는 한계가 있다.

그래서 나온 것이 유니코드이다.

유니코드는 전 세계 모든 문자에 대해 유일 코드를 부여한 것이다.

유니코드는 표기 방식이 여러 가지가 있는데 대표적으로 UTF8과 UTF16이 있다.

 

UTF8

알파벳과 숫자는 1바이트로 표현하고 아스키코드와 동일한 번호를 사용한다.

유럽 지역의 문자는 2바이트로 표현한다.

한글, 한자 등은 3바이트로 표현한다.

 

UTF16

알파벳, 숫자, 한글, 한자 등 거의 대부분을 2바이트로 표현한다.


문자열

 

문자들이 열을 지어서 모여있는 것을 말한다.

C 계열 언어에서는 문자열 끝에 널문자(\0)를 붙여서 문자열이 끝났다는 것을 표현한다.

만약 문자열 끝에 NULL이 없다면 메모리 상에서 문자열 이후의 값들도 의도치 않게

유출될 수 있다.(보안상 문제가 될 수 있음)

 

char str[] = "Hello World"; 

 

위와 같이 큰따옴표로 문자들을 묶어서 표현하게 되며 NULL은 우리 눈에만 안 보일뿐

자동적으로 문자열 끝에 입력되어 있다. 실제로 Hello World라는 문자열은 우리가 보기에

띄어쓰기까지 포함해서 총 11글자이지만 컴퓨터에서는 우리 눈에 보이지 않는

NULL문자까지 포함해서 12글자라고 인식한다.

'프로그래밍 언어 공부 > C++' 카테고리의 다른 글

열거형  (0) 2022.05.26
분기문, 반복문을 활용해 코딩 연습하기  (0) 2022.05.25
const와 메모리 구조  (0) 2022.05.23
비트 플래그  (0) 2022.05.22
환경설정, 정수  (0) 2022.05.19

본격적으로 C++ 프로그래밍 언어를 공부하기 위한 Visual Studio 설치를 진행한다. 
Visual Studio 설치 후 new project를 실행한다.


본격적으로 C++ 언어를 배우기 위한 첫 실행 화면이다.

역시나 새로운 언어를 배우면 국룰처럼 Hello World부터 시작한다.

실행시켜보면 콘솔창으로 해당 문자열이 정상 출력되는 것을 확인할 수 있다.

(주석은 기본적인 정보들이다)

 

어셈블리어에서 공부했던 개념이 그대로 적용된다.

초기값이 있다면 section .data 영역에 변수가 저장되고

초기값이 0이거나 없다면 section .bss 영역에 저장된다.

 

기본적으로 int 타입의 변수 hp를 생성해서 초기값으로 10을 주었다.

그리고 메인함수 내부에 문자열과 hp를 합쳐서 출력하는 코드를 만들었다.

보는바와 같이 정상적으로 출력되었다.

 

타입에는 크기에 따라 여러 타입이 있는데 아주 기본적인 타입을 예시로 들자면

char a; -> 1바이트 (-128~127)

short b; -> 2바이트 (-32,768~32,767)

int c; -> 4바이트 (-2.1억~2.1억)

__int64 d; -> 8바이트 (-어마무시한 값~어마무시한 값), (long long으로 표현하기도 함/ 초반에 언더바는 두번)

이런 식으로 있다. 

 

이런 타입의 크기가 다르기 때문에 상황에 따라 사용하는 타입이 달라진다.

메모리가 항상 부족한 콘솔이나 모바일의 환경의 경우 메모리 절약이 중요하기 때문에

적절한 변수 타입을 선택해서 사용해야 한다. 

 

또한 타입의 크기에 따라 숫자 범위를 알맞게 사용해야 한다. 타입의 크기를 벗어난 

숫자 범위를 사용하면 버그가 발생한다. 

 

ex)

a = 127;

a = a+1;

cout << a << endl; 

출력된 결과는 -128

 

위와 같은 상황을 정수 오버플로우라고 한다.

 

'프로그래밍 언어 공부 > C++' 카테고리의 다른 글

열거형  (0) 2022.05.26
분기문, 반복문을 활용해 코딩 연습하기  (0) 2022.05.25
const와 메모리 구조  (0) 2022.05.23
비트 플래그  (0) 2022.05.22
불리언, 부동소수점, 문자, 문자열  (0) 2022.05.20

+ Recent posts