• 배열참조형

참조형을 담는 배열은 생성할 수 없다

 

단 배열자료형의 참조형은 가능하다

 


  • 디폴트 매개변수

C++에서 새로 생겨났으며

 

매개변수에 기본으로 사용하는 값을 지정하여

함수 사용시 설정한 해당 매개변수를 기술하지 않으면 설정한 값으로 매개변수가 입력되는 기능

 

밑의 int b처럼 기본값을 설정해주면 된다

 

디폴트 매개변수은 규칙은 무조건 오른쪽에서 왼쪽으로 기술해야한다

 


  • 오버로딩

같은 함수의 이름으로 다른 매개변수, 다른 함수내용 을 정의 할 수 있는 기능

 

이 오버로딩은 객체프로그래밍의 다형성을 나타내는 기능중 하나이다

이 설명을 프로그래밍으로 나타내면

같은 종의 생물 = 같은 식별자

크기, 형태, 색깔 = 매개변수 리스트, 반환 자료형, 함수 내용  이라고 생각한다

 

식별자는 같지만 매개변수, 내용이 다르다

 

오버로딩을 할 때 주의 할 점은 매개변수 리스트는 필수로 무조건 달라야한다

 

반환 자료형이나 함수내용이 달라도 매개변수 리스트가 같으면 성립이 되지 않는다

 

이와 몇가지로 안되는 경우가 있는데

 

보통 함수에 이미 본문이 있을 때 이다

  • 매개변수의 const

코드상으로는 문제가 없지만 실행시 오류가 난다

 

이유는 같은 코드라고 컴파일러가 인식하기 때문

 

이는 int a나 const int a나 lvalue, rvalue모두 가능한 공통점 때문에 같은 코드라고 인식하는듯 하다

 

단 참조일 경우에는 다르다

참조일 경우에는 lvalue, rvalue 확실히 나누어지기 때문에 가능한 듯하다

 

 

※클래스의 멤버함수에서는 이런식으로 가능하다

 

  • * 와 [ ]

내가 생각하기로는 [ ]은 매개변수로 들어갈때 컴파일러가 포인터형으로 변환하는데

 

이때문에 같은 코드로 인식되어 실행이 불가능한 듯하다

 


  • 이름장식

c++은 오버로딩된 함수중 어떤것이 맞는지 어떻게 추적하냐면

이름장식(Name mangling)을 사용한다고 한다

 

함수 원형에 지정되어 있는 형식을 암호화 한다고 한다

 

예를들어

long Test(int) 를 암호화로 ?test@@YAXH@z

이런식으로 매개변수의 개수와 데이터형을 암호화한다고 한다

[컴파일러마다 암호 규칙이 다르다고한다]

 

이렇게 다른 암호화명으로 찾는듯 하다

  • inline함수

inline함수는 프로그램의 실행 속도를 높이기 위해 c++에서 새로 보강된것

 

함수가 하나 생성되면 함수의 시작 주소가 있을것이며

함수가 호출 될때 그 시작주소로 가서 실행 후 다시 원래 있던 주소로 돌아갈것이다

 

이를 더 자세히 하면

 

1. 함수 호출 명령

2. 함수 호출 명령 다음의 코드 주소를 메모리에 저장 [함수 종료 후 다시 돌아와야하니까]

3. 호출하려는 함수의 매개변수 복사 [파라미터에 넣어야하니까]

4. 호출하려는 함수의 주소로 점프

5. 함수 코드 수행

6. 함수 종료시 함수의 리턴값을 레지스터에 복사

7. 저장해 두었던 코드 주소로 점프

 

이러한 과정들이 있는데

inline은 이러한 문제를 어느정도 해결해준다

 

바로 함수를 호출할때 원본함수코드를 그냥 그자리에 붙여넣어서 

이동할 필요 없이 그 자리에서 읽고 처리한다

define과 비슷한 부분이다

 

이렇게 작성한 코드를 inline화 시키면

 

이런식으로 원본 코드가 온다는 말이다

 

inline의 사용법은 inline 이라는 키워드를 함수의 선언이나 정의 앞에 붙여주면 된다

 

inline이 속도는 굉장히 빨라지겠지만 만약 함수의 크기가 크다면

붙여지는 코드의 양도 그만큼 커져 프로그램이 무거워질 것이다 [ ※재귀함수는 불가능 ]

그렇기 때문에 그 기준을 잘 잡아야 하는데

 

이 기준은 다행히도 컴파일러가 알아서 해준다

얼마나 알아서 잘 해주냐면

 

우리가 inline키워드를 사용해도 컴파일러 판단에 부합하지 않으면 inline화 해주지 않는다

우리가 inline키워드를 사용하지 않아도 컴파일러 판단에 inline화 해준다

 

그러므로 우리가 inline키워드를 사용한다는것은 약간 요청보단 이건 어때? 라는 권유의 느낌 같다.

 

그리구 추가로 inline함수의 함수포인터를 사용해서 함수가 호출되었을때는 일반함수로 호출이 된다

 

이쯤 보면 매크로와 상당히 비슷한데

차이랄게 있다면

매크로는 단순히 코드를 변환시키는거지 값을 전달하지않는다

매크로 함수같은경우 값이 전달되는게아니라 문자 치환이여서

++a * ++a 가 되므로 "++" 연산자가 두번 실행된 후 곱셈이 진행되어 3 * 3으로 9가 나온다.

 


  • 참조변수

c++에 새로운 복합자료형이다

 

reference라고도 하며 미리 정의된 어떤 변수의 식별자 대신 쓸 수 있다

 

이 대신 사용한다는 것은 주소를 참조하여 사용한다는 의미이다 => 복사비용문제 해결

 

생성은 &를 붙여 생성한다

오른쪽 처럼 선언과 동시에 정의를 해주지않으면 생성 할 수 없으며

나중에 참조하는 변수를 바꿀수 없다

 

이 참조변수의 주된 용도는 매개변수에 사용하는데

 

기존 함수가 호출될때 매개변수에 들어온 값을 복사하여 사용하는데

이 참조형을 매개변수로 사용할시에 함수는 같은 주소를 가지고 있는 매개변수를 받기때문에 원본 데이터를 다룰수있다


만약 참조형에 다른 자료형이나 상수가 들어가면 에러가 난다

 

하지만 const를 사용하면 허용이 된다

이는 const일 경우 컴파일러는 임시변수를 생성하기 때문이다

long a를 int형으로 변환시켜 만든 임시변수 를 ra1가 참조하고

ra2 에 들어가는 상수 32를 가지고 있는 int형 임시변수 를 ra2가 참조하게 만든것이다

 

참조형은 참조 대상과 주소 값이 같다는 특성 때문에 참조 대상의 '별칭(alias)'이라고도 불린다. 

 

나무라서 좀 그렇지만 배울게 많다..

https://namu.wiki/w/%EC%B0%B8%EC%A1%B0%EC%97%90%20%EC%9D%98%ED%95%9C%20%ED%98%B8%EC%B6%9C

 

  • 함수포인터

함수도 주소를 가지고 있다 그 주소는 함수의 기계어 코드 시작주소를 가르킨다

괄호없이 함수의 이름만 작성하면 주소가 된다

이 함수 주소를 담는 포인터형도 있는데

반환형, 매개변수타입을 함수원형 처럼 써주면 되며, auto를 이용해 편하게 사용할 수 있다

책에서 auto는 배열처럼 리스트 형식을 초기화할 때는 사용할 수 없다고 하는데

기본 우리가 알던 배열 형식은 아니지만 initializer list로 적용이 된다

initializer list로 실행되는 모습

 

함수포인터의 자료형을 다루는걸 알았으니 함수의 매개변수에도 넣을 수 있다

 

함수포인터의 호출 방법은 두가지가 있다

 

1. 포인터이기에 *를 사용하여 함수에 접근해야한다

2. 함수이름이 그 함수를 지시하는 포인터이므로 그 함수를 가르키는 포인터도 함수이름처럼 사용해야한다

위 두가지가 모두 논리적으로 맞기에 둘다 허용된다

 

 

  • 함수와 2차원 배열

함수에 2차원 배열을 매개변수로 넣는것에 대해 설명하는 부분

 

함수의 원형 부분에 2차원 배열의 자료형을 기술할때 행의 개수는 필수로 입력하는게 핵심이다

7

https://ddidding.tistory.com/31

더블포인터에 이차원 배열의 이름이 대입되지 않는다 항목과 비슷한 개념이다

 


  • 함수와 문자열

문자열을 매개변수로 넣으려면 문자열의 첫번째 주소를 넣는다

C 스타일 문자열 예시

 

 


  • 함수와 구조체

구조체는 작성에 따라 메모리가 작을수도 있고 클수도있다

Test를 호출했을 경우 a가 복사되어 st에 대입된다

지금은 a의 크기가 작기에 이렇게 pass by value를 사용해도 괜찮지만

만약 a 크기가 크다면 이 복사과정이 부담이 될 수 있다

 

그래서 주소를 전달해 줄 수 있다

주소를 넘기는 방식중 passing by reference를 C++에서 제시한다고 한다

이건 뒤에 나오니까 뒤에서 정리한다

 

 


  • 함수와 std::array

stl array를 매개변수로 사용하고 Range based for loop를 사용하여 출력

 

 


  • 재귀호출

함수가 자기 자신을 호출할 수 있다 이걸 재귀호출이라 한다

 

간단한 로직은 if문을 통해 끝내는지, 자기자신을 호출하는지 분기를 나눈다

간단한 계승기능

위처럼 재귀함수는 for문으로도 서로 변환이 가능하다

 

재귀함수는 간결한 코드로 표현이 가능하나 스택에 계속 데이터가 쌓여 반복이 커진다면 stack over flow가 발생한다

 

알맞은 때에 사용해야 한다. 이 알맞은 때는 경험으로 이루어지면 될듯싶다

  • 더블포인터에 이차원 배열의 이름이 대입되지 않는다
더보기

 

배열의 이름은 첫번째 원소의 주소이다

a의 첫번째 원소는 int형의 주소, 그러므로 포인터에 대입이 가능하다

 

aa의 첫번째 원소는 &(aa[0][0])이 아니라 &(aa[0]) 이다

예로 

첫번째 원소는 int형을 5개 가진 aa[0]이고

두번째 원소는 int형을 5개가진 aa[1]이다.

고로 aa는 int[5]의 배열이다

 

그럼 &(aa[0]) 의 자료형은 int (*) [5](int형 5개를 가진 포인터)

int형의 더블포인터 와 int[5]를 가진 포인터는 다르다

 

paa는 int*의 주소이다(int**)

그러므로 int(*)[5]와 int** 는 다른 자료형이기에 대입이 되지않는다 

+1을 하면 더해지는 주소의 양이 다르다

 

이게 헷갈리는 이유중 하나는 둘다 참조를 두번하면 int형이 나오는게 동일해서일듯싶다

밑에서 aa[0][0]과 paa[0][0]의 자료형은 같다

aa[0]과 paa[0]의 자료형은 위에서처럼 다르다

 

배열자료형을 잊지말장

 

 


  • 포인터는 1차원배열과도 같다고 생각한다
  • 함수

함수가 return을 넘기는 과정

리턴 값을 CPU의 메모리or레지스터에 값을 복사해 저장한다

그 함수를 호출한 프로그램에서 리턴값이 들어있는 주소를 조사한다

※ 배열은 return이 안된다

 

함수의 원형

- 컴파일러에게 내가 저장한 return의 자료형이 이거야 라고 알려줌

- 매개변수의 타입과 개수를 컴파일러에게 알려줌

- 식별자 생략 가능(하지만 쓰자)

 

함수의 호출시 return처리

- 리턴값을 계산하여 리턴값을 CPU에 넣는다

- 넣을 때 함수머리부분의 정의된 자료형으로 넣는다

 


  • 매개변수

함수에 전달되는 값을 실제 매개변수(argument) 라한다

함수에 전달되어 복사받은 값을 저장한 변수를 형식 매개변수(parameter) 라한다

형식 매개변수는 지역변수로 생성된다

argument의 값을 복사해 parameter로 넣는다

 

그렇기에 둘다 값만 같고 다른 변수다

그 이유로 넣은 a와 b의 주소가 다르고 a의 값이 그대로이다

 

그래서 주소를 사용한다

함수의 정의에 있는 int b [ ]는 호출 될 때 새로 생성되었으며 a와 가르키는 배열의 데이터는 같다

 

근데 Test함수의 정의에 매개변수를 int b[ ]로 배열을 받게끔 사용했다

생성되는것도 배열이 생성될까 궁금했다

 

그래서 사이즈를 받아봤다

 생성되는 타입은 포인터인듯하다

 

이렇게 포인터로 넘어온다.

포인터는 크기에 제한이 없기에 조심하자

 

  • cctype.h

문자관련함수들

 


  • 삼항연산자

구성이다

expression1 ? expression2 : expression3

 

 

expression1이 true면 삼항연산자의 값은 expression2이며, 그 반대인 false면 값은 expression3이된다

 


  • switchcase

어떠한 정수자료형에 따른 분기를 나눌 때 사용하면 편하다

 

구성이다

switch ( integer-expression )

{

     case label1 : statement

     case label2 : statement

     ......

     default      : statement

}

 

integer-expression에 정수형 데이터가 들어가면 이 데이터와 같은 label의 행이 실행된다

 

주의 할 점은 시작된 구문 부터 계속 실행하기 때문에 break를 써주어 탈출해야한다

break를 안 했을 경우

integer-expression은 정수형은 모두 가능하기에 char, enum도 가능하다

 


  • break & continue

break는 나온순간 속해있는 Loop을 탈출한다

2번 반복문안에 break가 실행될때 속해있는 1번,2번 반복문을 탈출하는게 아니라 2번 반복문만 탈출한다

 

 

continue는 continue가 나온순간 뒤의 코드는 무시하고 반복문의 맨 처음으로 돌아가 조건을 확인한다

마찬가지로 속한 Loop을 기준으로 한다

 


  • 간단한 파일I/O

쓰기와 출력의 로직은 비슷하다

open( )으로 파일과 연결 ,연결한 파일에 관한 작업을 하고 , close( )로 파일연결 종료

 

먼저 파일에 쓰기다

<fstream> 에 정의 되어있는 ofstream 클래스는 Output File Stream으로

파일에 데이터를 작성가능한 기능을 가지고 있다

 

파일 읽기

<fstream> 에 정의 되어있는 ifstream 클래스는 Input File Stream으로

파일에 데이터를 프로그램으로 입력해주는 기능을 가진다

파일을 읽고 쓰는 법은 다양하다

 

나중에 더 자세히 나오니 이부분은 일단 어떻게 돌아가는지 로직만 이해하면 될거같다

 

*스트림 나중에 공부

  • End of File

파일의 끝에 도달했을 때 인식하고 프로그램에게 전달할 수 있다

다른 정규문자와 중복되지 않게 #define EOF -1 으로 지정되어있다

stdio.h

 

일단 redirection이라는 개념이 나왔다 File과 관련된 기능같은데

운영체제에서 제공하는 기능이며 입력이나 출력 등을 파일로 한다는 기능 같다

ex) 항상 키보드로 입력을 받았지만 파일의 데이터를 받아 입력으로 처리한다

 

window는 Ctrl + Z 를 누르는 것으로 EOF를 생성한다

^Z = Ctrl + Z

입력한 문자 개수 만큼 1이 출력된다(빈칸,엔터 포함)

두번째 입력했을때(ab^Zcdefg) Ctrl + Z 부분까지 인식하고 1이 3번 나왔다

 

그 뒤의 cdefg도 버퍼에 남았을까 싶어 다시 입력했지만 새로 입력한 문자개수만큼만 나왔다

이유는 EOF를 인식할 경우 그 뒤로는 입력을 받아들이지 않기 때문이다

 

근데 이상한점이 있다 분명 while문에 EOF를 만나면 종료하라고 되어있는데 한번 더 문자열을 입력 받게되는 상황이다

 

이는 밑의 블로그에 자세히 설명되어있다

간단히 하면 다른 문자가 먼저 입력된 상태에서 ctrl + z 를 입력하면 26의 값으로 처리된다고 한다

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=tipsware&logNo=221315155895 

 

[Q&A] EOF를 어떻게 입력하나요?

: C 언어 관련 전체 목차 http://blog.naver.com/tipsware/221010831969 1. 질문 EOF는 'End of file'...

blog.naver.com

ios_base 클래스에서 정의되어 있고
이를 상속받은 iostream, fstream, stringstream 모두 동일하게 작동합니다.

 

cin은 EOF를 인식했을 때 ios_base 클래스에 정의되어 있는 eofbit, failbit 이라는 비트를 1로 설정한다고 한다

이는 ios_base를 상속받은 iostream, fstream, stringstream 모두 사용한다

 

그래서 EOF를 만났는지 안만났는지 알수있는법은 저 비트를 확인하면 되는데

 

eofbit는 cin.eof( ) 를, failbit는 cin.fail( ) 을 사용하면 알수있다

 


  • 2차원배열

말그대로 2차원처럼 보이는 배열이다

초기화

 

사실은 1차원으로 쭉 나열되어있긴하다

 

일차원배열과 비슷하게 [0]과 [0][0]의 주소는 같다 

 


  • if

조건에 따라 실행하는 구문이 생길때 사용한다

 

구성은

if ( test-condition )

   statement

 

test-condition이 참이면 statement를 수행한다

거짓이면 statement를 건너뛴다

 

거짓인 경우 다시 다른 조건을 확인하는 else if

 

거짓인 경우 무조건 수행하는 else

 


  • 논리표현식

한가지 이상의 조건이 논리연산자를 통해 맞는지(True) 아닌지(False) 값을 나타내는 표현식

 

 

1. || (논리합, OR) - 두개의 조건을 검사하며 둘중 하나라도 True면 True리턴 , 

                         그리고 시퀀스 포인트이기에 좌변의 부수효과가 있다면 || 에서 무조건 실행되고 우변이 평가된다

 

b는 0으로 초기화 되어 있다

 

첫조건 b++ > 0 에서  ++는 접미에 있기에 > 보다 연산자 순위가 낮기에 >먼저 실행된다

 

그럼 0 > 0 이므로 false

 

그후에 || 가 시퀀스 포인트이므로 증가연산자가 실행된다(이때  b = 1)

 

그리고 다음 조건인 b > 0 을 실행한다

 

두번째 조건에서는 b가 1이기에 1 > 0 이므로 최종으로 true이다

 

 

 

2. && (논리곱, AND) - 두가지 조건을 검사하고 모두 True여야 연산의 결과가 True이다

 

 

 

3. ! (논리부정, NOT) - 하나의 조건의 값을 뒤집는다 ( True -> False, False -> True )

                             &&, || 보다 우선순위가 높은 편이다

 

논리부정은 0(Null)인지 아닌지 체크하는데 편리하다

 

 

+ Recent posts