1. size()의 결과를 0과 비교할 생각이라면 차라리 empty를 호출하자

  • size()의 결과와 0을 비교하는 것은 empty()를 호출하는 것과 본질적으로 똑같습니다. 하지만 size()는 항상 상수 시간에 수행된다는 보장이 없고, empty()는 항상 상수 시간에 수행됩니다.이유는 list의 splice 함수와 밀접한 관련이 있습니다. splice 함수는 객체의 복사를 하지 않고, list의 특정 요소들을 다른 list로 옮길 수 있는 함수입니다.

    list의 size()가 상수 시간에 수행되도록 하려면, list 객체 내에 리스트의 요소가 몇 개 존재하는지를 담아두는 멤버를 하나 준비하고, 요소의 수를 변경시킬 수 있는 모든 경우에 이 멤버 변수의 값을 갱신 해야 합니다.

    물론 splice 함수도 마찬가지로 요소의 수를 담는 멤버 변수를 갱신 해야 하고, 이를 위해서 splice가 호출될 때마다 옮긴 요소의 수를 세어야 하므로, splice 함수가 상수 시간에 수행되도록 만들 수가 없게 됩니다.

    여러 STL 제품에서 list를 다르게 구현해 놓고 있습니다. 예상하고 있겠지만 구현을 맡은 개발자가 size와 splice 중 어디에 비중을 두고 있는지에 따라, splice가 상수 시간에 수행되는 대신 size가 상수 시간에 수행되지 않을 수도 있고 그 반대일 수도 있습니다.

    지금 쓰는 라이브러리의 list에서 size()가 상수 시간에 수행된다고 하더라도 나중에 라이브러리를 교체하거나, 다른 플랫폼으로 포팅할 일이 생길 지도 모릅니다. 그러므로 size()의 결과를 0과 비교하기보다는 empty()를 호출하는 것이 좋습니다.

 

 

 


2. 단일 요소를 단위로 동작하는 멤버 함수보다 요소의 범위를 단위로 동작하는 멤버 함수가 더 낫다

  • 단일 요소를 단위로 동작하는 멤버 함수(이하 단일 요소 함수)보다 요소의 범위를 단위로 동작하는 멤버 함수(이하 범위 멤버 함수)가 성능 면에서 더 낫습니다. 만일 단일 요소 함수를 사용하여 여러 요소를 삽입하려면, 반복문을 사용할 수 밖에 없습니다. 반복문을 사용하여 요소를 하나씩 삽입하면 타자량도 많고, 가독성도 그다지 좋다고 할 수 없습니다.


    1. vector<Widget> v1, v2;                // v1과 v2는 Widget을 담는 벡터라고
    2.                                     // 가정합시다.
    3. ...
    4.  
    5. // v1의 내용을 v2의 뒷쪽 반과
    6. // 똑같이 만드는 가장 빠른 방법은
    7. // 무엇일까요?
    8.  
    9. // 정답은 assign을 사용하여
    10. // 다음과 같이 짧게 작성할 수 있습니다.
    11.  
    12. v1.assign(v2.begin() + v2.size() / 2, v2.end());
    13.  
    14. // 반복문을 사용하면
    15.  
    16. v1.clear();
    17. for (vector<Widget>::const_iterator ci = v2.begin() + v2.size() / 2;    ci != v2.end();    ++ci) {
    18.         v1.push_back(*ci);
    19. }
    20.  
    21. // 하지만 assign을 호출하는 것이
    22. // 손이 덜 간다는 것은 뻔합니다.
    23.  
    24. // 루프를 피하는 한 가지 방법은
    25. // 알고리즘을 사용하는 것입니다.
    26.  
    27. v1.clear();
    28. copy(v2.begin() + v2.size() / 2, v2.end(), back_inserter(v1));
    29.  
    30. // 타자량이 훨씬 많이 줄긴 했지만,
    31. // assign을 사용한 예제보다는
    32. // 여전히 타자량이 많습니다
    33. // (약간이지만...).
    34.  
    35. // 게다가 copy의 내부를 보면
    36. // 결국 루프를 사용하여 구현되어 있습니다.
    37.  
    38. // 삽입 연산자(inserter, back_inserter,
    39. // front_inserter)를 사용해서 복사 대상
    40. // 범위를 지정하는 copy는 거의 모두
    41. // 범위 멤버 함수로 바꿀 수 있고,
    42. // 바꿔야 합니다.
    43.  
    44. // 위의 copy는 insert의 범위 함수
    45. // 버전으로 대체할 수 있습니다.
    46.  
    47. v1.insert(v1.end(), v2.begin() + v2.size() / 2, v2.end());
    48.  
    49. // copy는 복사의 의미에 초점이 맞춰진 반면,
    50. // insert는 삽입의 의미에 초점이 맞춰져
    51. // 좀 더 명확하게 의미 전달이 됩니다.


    단일 요소 멤버 함수보다 범위 멤버 함수가 더 좋은 이유를 이미 두 가지나 확인했습니다.
    • 범위 멤버 함수를 사용한 코드가 대개 짧다(즉, 프로그래머의 손이 덜 아프다).
    • 범위 멤버 함수는 훨씬 명확하고 간결한 의미를 전달한다.

 

 

 

  • 만일 배열에 있는 데이터를 벡터의 앞 부분으로 옮긴다고 생각해 봅시다. 이 경우 단일 요소 함수를 쓰는 것 보다 범위 멤버 함수를 쓰는 것이 좋은 이유가 3 가지나 있습니다. 첫째, 단일 요소 함수는 배열의 멤버 수 만큼 호출되어야 하지만, 범위 멤버 함수는 딱 한 번만 호출되면 되므로 함수 호출 비용이 적게 듭니다. 물론 인라인 함수인 경우에는 차이가 없지만 모든 단일 요소 함수가 인라인인 것은 아닙니다.
  • 둘째, 벡터에 들어 있던 기존의 데이터들을 미는 횟수에서 차이가 납니다. 단일 요소 함수는 배열의 요소들을 하나 씩 삽입하기 때문에 총 복사 횟수는 (배열의 총 요소 수) * (벡터에 들어 있던 요소의 수) 만큼이 됩니다. 반면 범위 멤버 함수의 경우 몇 개가 삽입되는지를 미리 알 수 있기 때문에, (벡터에 들어 있던 요소의 수) 만큼만 복사(딱 한번만 밉니다)가 일어납니다.
  • 셋째, 메모리 할당에 관한 것입니다. 대부분의 경우 벡터는 메모리가 꽉 찰 때마다 자신의 용량을 두 배로 늘리도록 구현이 되어 있습니다. 즉 n개의 새 데이터 요소를 하나씩 삽입하려고 하면 메모리 할당을 log2n번이나 하게 되는 셈입니다. 반면 범위 멤버 함수를 쓰면 삽입할 요소의 수를 미리 알 수 있으므로 딱 한 번 필요한 메모리를 할당하면 됩니다.
  • vector에 대해서 설명드린 내용은 string에서도 동일하게 적용됩니다. deque의 경우에는 비슷하긴 하지만 vector나 string과는 다른 메모리 관리 방식을 취하고 있어서 "반복적인 메모리 재할당"에 관한 이야기는 맞지 않습니다. 하지만 불필요하게 빈번한 컨테이너 내 요소의 이동이나, 불필요한 함수 호출에 관한 이야기는 일반적으로 맞습니다.
  • list 역시, 범위 멤버 함수가 단일 요소 함수보다 수행 성능에서 우수합니다. 되풀이되는 함수 호출에 있어서는 역시 범위 버전이 좋습니다. 하지만 list는 노드 기반으로 동작하기 때문에 메모리 할당에 관한 사항은 딱 맞지 않습니다. 그 대신에 리스트의 노드를 연결하는 next 포인터와 prev 포인터 값이 불필요하게 되풀이해서 세팅되는 문제가 생깁니다.
  • 최소한 표준 시퀸스 컨테이너에 대해서는, 단일 요소 버전의 삽입이냐, 범위 버전의 삽입이냐를 선택하는데 있어서 "프로그래밍 스타일"을 압도하는 많은 요인들을 내새울 수 있게 되었습니다. 그렇다면 연관 컨테이너에 대해서는 어떨까요? 단일 요소 버전의 insert에서 여전히 반복 함수 호출의 오버헤드가 있긴 하지만 딱 부러지게 효율이 어떻다라고는 말씀드리기 힘듭니다. 게다가 몇 가지 특수한 종류의 범위 삽입 함수들의 최적화의 여지를 가지고 있지만 이론적으로만 이러한 최적화가 존재합니다.하지만 연관 컨테이너에서 범위 멤버 함수를 쓴다고 해서 효율이 뒤진다든지 하는 것은 없으니 지금 쓰셔도 잃는 것은 없습니다.

    굳이 효율 문제가 아니더라도, 타자수를 줄여주고 나중에 읽기도 편해 이해하기 좋기 때문에 연관 컨테이너에서도 범위 멤버 함수를 쓰는 것이 좋습니다.
  • 범위를 지원하는 멤버 함수는 어떤 것인지 미리 알아놓고 정리해 두면, 나중에 이것들을 사용할 기회를 포착하기가 매우 쉬울 것입니다. 
  •  


    1. // 다음에 나온 시그너쳐(signature)에서,
    2. // 매개 변수 타입인 iterator는 말 그대로
    3. // 컨테이너의 반복자 타입, 즉 container::iterator
    4. // 란 뜻입니다.
    5.  
    6. // 한편 InputIterator는 어떤 입력
    7. // 반복자도 받아들일 수 있다는 뜻입니다.
    8.  
    9.  
    10. //-----------------------------------------------------------------------------
    11. // ※ 범위 생성(Range Construction)
    12. //   모든 표준 컨테이너는 다음과 같은
    13. //   형태의 생성자를 지원하고 있습니다.
    14.  
    15. container::container(InputIterator begin,        // 범위의 시작
    16.                     InputIterator end);            // 범위의 끝
    17.  
    18. // 이 생성자에 넘겨진 반복자가
    19. // istream_iterator 혹은
    20. // istreambuf_iterator이면
    21. // C++에서만
    22. // 볼 수 있는 가장 황당한 분석
    23. // 결과(parse)가 생깁니다.
    24.  
    25. // 이것 때문에 컴파일러는 이것을
    26. // 컨테이너 객체의 정의로 보지 않고
    27. // 함수 선언으로 이해하고 말지요.
    28.  
    29.  
    30.  
    31. //-----------------------------------------------------------------------------
    32. // ※ 범위 삽입(Range Insertion)
    33. //   모든 표준 컨테이너는 다음과 같은
    34. //   형태의 insert를 지원하고 있습니다.
    35.  
    36. void container::insert(iterator position,        // 범위를 삽입할 위치
    37.                     InputIterator begin,        // 삽입할 범위의 시작
    38.                     InputIterator end);            // 삽입할 범위의 끝
    39.  
    40. // 연관 컨테이너는 자신이 가지고 있는
    41. // 비교 함수를 사용하여 삽입될 요소가
    42. // 놓일 위치를 결정하기 때문에 위치
    43. // 매개 변수를 가지고 있지 않은
    44. // 시그너쳐를 제공합니다.
    45.  
    46. void container::insert(InputIterator begin, InputIterator end);
    47.  
    48. // 단일 요소 버전의 insert를
    49. // 범위 버전으로 교체할 부분을 찾을 때
    50. // 잊지 말아야 할 것이 있습니다.
    51.  
    52. // 바로 단일 요소 함수 중에 몇몇은
    53. // 다른 함수 이름으로 위장하고
    54. // 있다는 사실입니다.
    55.  
    56. // 예를 들어, push_front와
    57. // push_back은 하나의 요소를
    58. // 컨테이너에 넣는 함수이지만 "삽입"
    59. // 류로 불리지 않지요.
    60.  
    61.  
    62. //-----------------------------------------------------------------------------
    63. // ※ 범위 삭제(Range Erasure)
    64. //   역시 표준 컨테이너에서 범위 버전의
    65. //   erase를 제공하고 있지만, 반환 타입은
    66. //   시퀸스 컨테이너와 연관 컨테이너에
    67. //   대해서 각각 다릅니다.
    68.  
    69. // 시퀸스 컨테이너에선 다음과 같은
    70. // 형태를 쓸 수 있고,
    71.  
    72. iterator container::erase(iterator begin, iterator end);
    73.  
    74. // 반면에 연관 컨테이너에서는 다음과
    75. // 같은 형태를 쓸 수 있습니다.
    76.  
    77. void container::erase(iterator begin, iterator end);
    78.  
    79. // 반환 타입이 다른 이유는
    80. // 연관 컨테이너 버전의 erase에서
    81. // 지워진 요소의 바로 뒤에 있는
    82. // 요소를 가리키는 반복자를
    83. // 반화하게 하면 납득하기 힘든
    84. // 수행 성능 저하가 생길 수 있다고
    85. // 합니다.
    86.  
    87. // vector와 string의 insert에 대한 이야기가
    88. // erase에서 통하지 않는 부분은 반복되는
    89. // 메모리 할당에 있습니다.
    90.  
    91. // vector와 string의 메모리는
    92. // 새 데이터 요소를 넣을 때에는 자동으로
    93. // 커지지만 내부의 요소 수가 줄어들
    94. // 때에는 자동으로 작아지지 않기
    95. // 때문입니다
    96.  
    97.  
    98. //-----------------------------------------------------------------------------
    99. // ※ 범위 대입(Range Assignment)
    100. //   모든 표준 시퀸스 컨테이너는
    101. //   범위 버전의 assign을 제공하고
    102. //   있습니다.
    103.  
    104. void container::assign(InputIterator begin, InputIterator end);
    105.  



 

참조 : http://ajwmain.iptime.org/programming/book_summary/%5B02%5Deffective_stl/effective_stl.html#I04

 

Effective STL 정리

매우 긴 문자열을 담을 수 있는 string 류의 컨테이너(string-like container for very large strings) 이 컨테이너는 rope(로프) 라고 불립니다. SGI는 로프를 이렇게 규정하고 있습니다. 로프는 확장성을 갖춘 문

ajwmain.iptime.org

 

C++ 기초를 복습하고 나서 코딩테스트 문제를 풀다보면 직접 구현할수도 있지만 이미 구현되어있는 자료구조, 알고리즘을 불러오면 쉽다는걸 느꼈다..

 

처음에는 STL 왜쓰는지.. 그냥 직접 구현하면 되는거 아닌가 했더니 사용해보니 진짜 편하긴하다..

 

그래도 쓰기전에는 꼭 직접 모든것을 구현해보자... 어떻게 동작하고 어떤 원리인지는 알고 써야지..

 


STL에는 많은 컨테이너가 있다.  ( 자료구조라 생각하면 편함 )

  • 표준 STL 시퀸스(sequence) 컨테이너: vector, string, deque, list.
  • 표준 STL 연관(associative) 컨테이너: set, multiset, map, multimap.
  • 비표준 시퀸스 컨테이너: slist(단일 연결 리스트), rope(대용량 string).
  • 비표준 연관 컨테이너: hash_set, hash_multiset, hash_map, hash_multimap.
  • STL에 속하지 않은 표준 컨테이너: 배열(C++ 배열), bitset, valarray, stack, queue, priority_queue. 

 

이렇게 많은것중 한가지만 알면 당연히 안된다.. 각각의 특징을 이해하고 언제 어떤것을 사용할지를 정리하는것이 이 글의 목표....   

 

우선, STL 컨테이너는 연속 메모리(continuous-memory) 컨테이너와 노드 기반(node-based) 컨테이너로 나눌 수 있다.

 

  • 연속 메모리 컨테이너( 배열 기반 컨테이너 )
    동적 할당된 하나 이상( 대개 하나 )의 메모리 단위( chunk )에다가 데이터 요소를 저장해 두는 컨테이너입니다. 새 요소가 삽입되거나 이미 있던 요소가 지워지면(erase), 같은 메모리 단위에 있던 다른 요소들은 앞 혹은 뒤로 밀려나면서 새 요소가 삽입될 공간을 만들던지, 지워진 공간을 메웁니다. 이러한 "밀어내기" 때문에 수행 성능의 발목을 잡을 수 있고, 예외 안전성(exception safety)에도 영향을 미칩니다.
    여기에 속하는 컨테이너는 vector, string, deque입니다. 비표준 컨테이너인 rope 역시 연속 메모리 컨테이너입니다.

 

  • 노드 기반 컨테이너
    동적 할당된 하나의 메모리 단위에다가 하나의 요소만을 저장합니다. 컨테이너 요소를 삽입 혹은 삭제했을 때 노드의 포인터만이 영향을 받지, 노드의 내용은 그대로입니다. 따라서, 삭제나 삽입이 일어났다고 해도 나머지 요소들이 밀려난다든지 하는 일이 없습니다.

    연결 리스트를 나타내는 컨테이너, 즉 list와 slist가 노드 기반이고, 표준 연관 컨테이너 모두가 노드 기반 입니다(이것들은 전형적으로 균형 트리(balanced tree)로 구현되어 있습니다).

 

  • 이제는 "어떤 상황에 어떤 컨테이너를 쓰면 가장 좋을까?"에 관련된 문답을 수월하게 정리할 수 있을 것입니다.
    • 인덱스를 통한 요소 삽입 가능해야한다. -> 시퀀스 컨테이너
    • 요소들의 순서에 관심 없다 -> 해쉬 컨테이너
    • 반복자 타입에 대한 구분
      • 임의 접근 반복자 : vector, deque, string
      • 양방향 반복자 : slist와 해쉬 컨테이너는 쓸 수 없다
    • 요소 삽입 삭제시 다른 요소가 밀려나는일 없어야한다 : 연속메모리 컨테이터는 불가
    • C의 데이터 타입과 메모리 배열 구조적으로 호환되어야 한다 : vector 밖에 쓸 것이 없다.
    • 탐색 속도가 중요하다 : 해쉬 컨테이너, 정렬된 vector, 그리고 표준 연관 컨테이너
    • 컨테이너의 참조 카운팅이 신경 쓰이나요? 그렇다면 string 가까이에는 가지 않는 것이 좋습니다. 많은 string 코드가 참조 카운팅이 되도록 구현되어 있습니다. 이럴 때 vector<char>를 쓰는 것입니다.
    • 삽입 삭제가 안정적 : 노드 기반 컨테이너를 고려해 보시기 바랍니다.
    • 트랜잭션적인 삽입이 여러 개의 요소(범위로 주어집니다)에 대해 이루어져야 할 경우에는 list를 선택합니다. 
    • 반복자, 포인터, 참조자가 무효화(포인터가 가리키고 있던 메모리의 실제 내용이 없어지는 일을 뜻한다)되는 일을 최소화해야 하나요? 이런 경우에는 노드 기반 컨테이너를 사용하기 바랍니다. 노드 기반 컨테이너는 노드 삽입과 삭제가 일어나도 기존의 반복자나 포인터 혹은 참조자가 무효화되지 않기 때문입니다(가리키고 있는 요소를 삭제하지 않는 한 말이죠). 반대로 연속 메모리 컨테이너는 전체적인 메모리 재할당이 빈번하게 일어나기 때문에 반복자나 포인터, 참조자가 무효화되기 쉽습니다.
    • 임의 접근 반복자를 지원하는 시퀸스 컨테이너가 필요한데, 요소 삭제가 일어나지 않고 요소 삽입이 컨테이너의 끝에서만 일어나는 한, 포인터와 참조자가 무효화되지 않는 것이 필요한가요? 아주 특별한 경우이긴 하지만, 어쩌다 이런 경우를 만난다면 deque가 정답입니다. deque는 요소 삽입이 끝에서 일어날 때 반복자만 무효화되는 재미있는 컨테이너입니다(STL 컨테이너 중 포인터와 참조자를 무효화시키지 않고 반복자만 무효화되는 것은 deque가 유일합니다).

 

참조 : http://ajwmain.iptime.org/programming/book_summary/%5B02%5Deffective_stl/effective_stl.html#I04

CHAPTER 8. 객체와 클래스

 

8.1 객체지향 프로그래밍 시작을 위해

 

프로그래밍 방법의 종류

방법 설명
순차적
프로그래밍
프로그램 코드를 주어진 작업 순서대로 나열
구조적
프로그래밍
프로그램 실행을 위해 필요한 기능을 확인하여 해당 기능들을 독립적으로 작성 후 함수를 호출해서 작업하는 방식
객체지향
프로그래밍
객체를 설정하여 그에 해당하는 정보와 실행하는 기능을 포함시키는 방법
- 추상적인 개념을 실체화 시키는 방법이다. ( 기본 프로그래밍 방법 )

 

Def . 클래스

  • 클래스는 멤버변수(구조체)와 멤버함수(함수)로 구성 되어있다.
  • 데이터와 함수를 저장할수 있는 캡슐형 자료형이라 생각할 수 있다.

 

 

지금까지 배운 자료형들 비교

일반 자료형 문자열 구조체 클래스
한가지 종류의 데이터를 한 개 저장할 수 있다. 한가지 종류의 데이터를 여러 개 저장할 수 있다. 여러가지 종류의 데이터들을 저장할 수 있다. 여러가지 종류의 데이터들과 함수들을 저장할 수 있다.
Ex ) 
int a
Ex) 
char a[30]
Ex) 
typedef struct
{
Int a[30]
Char flag
} example
Ex)
Class example
{
Public :
Int a
Void function()
}

 

 

  • 객체 지향에서 문제 해결의 시작점은 작업 순서가 아닌 누가 문제를 무엇으로 어떻게 풀어 나가는 것인가이다. 

( 누가 객체 무엇 멤버변수 어떻게 멤버함수 )

 

 

 

 

 

8.2 객체지향 프로그래밍

Def .  객체와 클래스

  • 클래스는 자료형에 해당하는 것이고 객체는 변수에 해당하는 것이다. 단지 변수는 하나의 값을 기억하지만, 객체는 여러 값을 기억하고 동작하는 코드도 포함한다.

 

객체지향 프로그래밍의 작업 순서

문제 분석 -> 객체 식별 -> 해당 객체의 클래스 정의 -> 객체 생성(선언)

 

 

클래스의 구성

멤버변수 상태를 저장 데이터 값을 저장 )
멤버함수 멤버 변수를 이용하여 자료 처리와 같은 동작을 수행함

 

 

클래스 생성 방법

헤더파일에 작성!!
 
Class 클래스이름
{
클래스 멤버
} //  여기서 중요한 것은 반드시 클래스 선언이 끝난 다음에는 세미콜론 입력!
 
이후에 객체 생성은 그냥 단순히 변수 선언과 똑같아

 

 

Def. 멤버 접근 속성

  • 약간 보면 클래스 자체가 하나의 프로그램? 같아 보여 나는 혼자 변수 선언도 하고 함수도 가지면서 내부에서 기능도 수행 가능하고 약간 그렇게 생각해도 될 거 같아 마치 우리가 헤더파일을 작성하면 include 예약어를 통해서 내용을 불러오는 것처럼 클래스도 각각의 멤버들에 접근을 하려면 한가지의 조건이 필요해
  • 클래스 멤버의 접근 속성에는 private, protected, public이 있다. 이 중 private가 클래스 멤버의 기본 속성이다. 해석 그대로 
  • Private는 main함수에서 접근이 불가능하다는 것이다. 
  • Protected는 클래스 상속에 대해 공부를 하고 설명을 할것이다.
  • Public은 private와 반대로 main함수에서 접근이 가능하다는 것이다. 

 

 

멤버 속성 정의 방법

Class 클래스이름
{
Public : 
속성을 public으로 할 멤버 변수 또는 함수 작성

Protected : 
속성을 protected로 할 멤버 변수 또는 함수 작성
 
Private :
속성을 private로 할 멤버 변수 또는 함수 작성
};  

 

CHAPTER 6. 함수

 

6.1 함수의 역할

 

 

Def . 함수의 종류

  설명
표준함수 프로그램상 이미 정의 되어있는 함수
사용자 정의 함수 기능이 정의되어 있지 않아 사용자가 직접 정의한 함수
Main() 함수 프로그램 실행에서 프로그램의 시작과 끝을 담당하는 함수

함수를 사용하기 위해서는 해당 함수의 정보를 가진 헤더파일을 반드시 프로그램에 포함 시켜야 한다. Iostream.h에 표준함수가 포함 되어있다.

 

 

 

 

Def . 함수의 프로토 타입

  • 프로토 타입은 해당 함수 사용에 필요한 정보로 함수 입력 시 프로그램에서 나오는 말풍선이다.

 

 

 

프로토 타입의 구성

항복 의미 함수의 프로토타입에서
입력 여러 가지 입력 가능 매개변수
함수 함수를 구분하는 함수 이름 함수 이름
결과 함수는 주어진 기능을 수행하고 하나의 결괏값을 가져올수 있다. 이를 반환한다.’ 또는 반환값이라 한다. 그 이유는 함수의 마지막에 반환값을 알리는 명령이 return이어서 그대로 부르거나 해석해서 되돌린다 라고 부르기도 한다. 반환값

 

함수반환값 함수이름(매개변수,….)

함수 반환 값은 함수 실행 후 반환하는 값의 자료형을 의미, 만약 반환 값이 없으면 void로 표시

 

 

 

 

6.2 사용자 정의 함수          

  • 사용자 정의함수 작성 순서
    1. 함수에서의 작업 순서 결정 정의 내용 결정 )
    2. 프로토 타입 결정 리턴형, 함수 이름, 매개변수 )
    3. 함수 정의
    4. 함수 테스트

 

사용자 정의함수 예시

bool Caltime(const int sec, int& h, int& m, int& s)
{
           if (sec < 0)
                      return false;
 
           int sec1,sec2;
           h = sec / 3600;
           sec1 = sec % 3600;
           m = sec1 / 60;
           sec2 = sec1 % 60;
           s = sec2;
 
           cout << "입력한 시간 = " << h << "시" << m << "분" << s << "초"
           return true;
}

 

 

 

 

6.3 해더 파일 작성에서 전처리기 사용

  • 프로그램이 복잡해지면 하나의 헤더파일을 여러 번 참조하게 되는 경우 재정의로 인한 오류가 발생하게 된다. 이를 방지하기 위해 컴파일에서 해당 코드를 한번만 참조하게 하는 전처리기를 사용한다.
  • 헤더 파일 작성시 항상 ifndef 구문을 사용해서 오류를 방지하자

 

 

Def . ifdef 구문

형태
#ifdef AAA
{내용1}
#else
{내용2}
#endif
AAA가 define되어 있으면 즉 선언이 되어있으면 {내용1}을 수행 만약 선언 안 되어있으면 {내용2수행

 

Def . ifndef 구문

형태
#ifndef AAA
{내용1}
#else
{내용2}
#endif
AAA가 define되어 있으면 즉 선언이 되어있으면 {내용2}을 수행 만약 선언 안 되어있으면 {내용1수행

 

Ex. 헤더파일 작성 예시

#ifndef _해더파일 이름을 대문자로 표시_H_
#define _해더파일 이름을 대문자로 표시 _H_
{선언 내용}
#else
#endif
만약 example.h라는 헤더파일이 있으면 _EXAMPLE_H_ 로 표시후 선언할 내용을 #define _EXAMPLE_H_
여기에 적으면 됨

 

 

 

 

6.4 함수의 매개변수 전달

  • 함수 선언 시 필요한 매개변수를 선언한다. 이때 선언된 매개변수들은 main함수에서 선언된 변수들과 달리 따로 저장공간이 확보된다. 쉽게 생각하면 main 함수 내에서의 저장공간과 표준함수 또는 사용자 정의 함수의 저장공간은 분리 되어있다. 이러한 특징 때문에 매개변수를 입력하는 방법이 크게 두가지로 구분이 된다.
  • 함수내에 필요한 변수를 입력하는 방법은 크게 두가지이다. 전달 받은 매개변수를 변환 가능한 방법과 변환이 불가능한 방법.
  • 전달 받은 매개변수를 main함수 내에서도 값을 수정하는 방법은 Call by Reference 즉 주소를 입력하면 된다.
  • 전달 받은 매개변수를 main함수 내에서 값이 수정 안되게 하는 방법은 call by value 즉 값을 직접 전달하는 방법이다.

 

 

 

 

Def . Call by Value

  • 함수에 필요한 내용을 입력할 때 직접 main함수 내에 있는 변수에 저장되어 있는 값을 전달하는 방법이다.

 

EX

Int b=200
Example1(b);
Example1(999);
 
Int example1( int a )
{
Cout << a << Endl;
A=184;
}

Example 이라는 함수에 변수 b에 저장 되어있는 값을 전달하는 것과 직접 값을 입력한 예시이다.

이때 example함수 속 변수 a에 main함수의 변수 b의 내용 200이 전달되었고 a값이 함수 속에서 수정이 되었다. 이때 수정되는 것은 함수 속 a값이지 main함수의 b의 내용은 변하지 않는다.

 

 

 

 

Def . Call by Reference

  • 함수에 주소를 전달하여 입력된 매개변수를 참조할 수 있도록 하는 방법이다.
  • 이 방법에는 포인터 변수를 사용하는 방법과 레퍼런스 변수를 사용하는 방법 총 두가지가 있다.

 

 

EX1 ( 레퍼런스 변수 사용 )

Int example2( int &a )
{
 Cout << a << Endl;
 A = 200;
 Cout << a << Endl;
}
 
Int b=100;
Int &r_b=b;
 
Example2(r_b);

Example2 함수는 레퍼런스 변수를 매개변수로 사용한다 

즉 함수에 입력된 main함수의 변수를 수정하는 것이다.

 

 

포인터 변수를 사용하는 방법도 비슷한 과정이다.

EX2 ( 포인터 변수 사용 )

Int example3(int *a)
{
 Cout << *a << Endl;
 *a=200
 Cout << *a <
}
 
Int b=200;
Int *p=&b;
 
example3(&b) //= example3(p)

이것도 마찬가지로 매개변수를 포인터 변수로 지정했다. 그러므로 함수에 입력되는 내용은 변수의 주소이다. 그러므로 함수내에서 변수의 수정이 있으면 주소를 통해 main함수의 변수의 값을 수정하게 된다.

 

 

 

 

 

 

 

Def . 디폴트 매개변수

  • 함수에는 매개변수에 값이 입력이 되어야한다. 하지만 프로그래머가 함수의 매개변수의 초기 값을 설정하여 함수 호출에서 함수의 매개변수를 지정하지 않은 경우 해당 초기 값을 호출한 함수에서 사용할 수 있다.

 

형태

Int example1( int a =200 )
{
Cout << a << Endl;
A=184;
}

그저 그냥 함수의 프로토 타입에서 매개변수 선언 시 초기화를 해주면 된다.

이렇게 만들어 두면 만약 매개변수 입력을 안 하면 초기값을 불러와서 그 값을 입력한 것과 동일한 결과가 나온다.

 

 

 

 

6.5. 함수와 const의 활용

Def . const

  • 이는 기호 상수를 정의하는 예약어 이다. 함수 프로토 타입에서 매개변수 앞에 const를 적어주면 이는 함수 내에서 변수의 값이 변하지 않는다는 것을 의미한다.

 

  • 사용자 정의 함수 작성시 매개변수를 정하는 규칙
    1. 함수의 입력값으로 사용한다 ( const 지정 )
    2. 함수의 처리 결괏값이 함수 호출 후 사용된다. ( call by reference로 매개변수 할당 )
    3. 함수 반환값은 함수의 처리가 성공적으로 수행했는가를 나타내는 것이 편리하다. ( 성공시 0, 에러시 -1 )

 

 

6.6. 함수의 오버로딩

  • 함수 선언 시 만약 매개변수 또는 출력값의 변수만 다르고 함수의 내용은 같다면 우리는 함수의 이름을 계속 다르게 설정해야 하는 미련한 짓을 한다. 이를 방지하기위해 오버로딩 즉 중복 정의가 있다.
  • 프로그램 내에서 함수를 식별하는 항목은 총 3가지가 있다. 1. 함수 반환형 2. 함수 이름 3. 함수 매개변수 이 3가지중 하나라도 다르면 다른 함수가 된다.
  • 이러한 특징을 통해 프로그래머들은 함수 이름은 같게 설정 후 여러가지 자료형을 사용하는 함수 여러 개를 설정해 프로그래밍을 좀더 효율적이게 할 수 있다.

 

 

6.7. 구조체를 함수의 인수로 사용

  • 6.4의 매개변수 전달 내용에서 그냥 구조체 선언하고 매개변수를 구조체로 선언하면 끝..

CHAPTER 5.논리적 자료표현 구조체

 

5.1 구조체

 

5-1-1. 구조체

 

Def. 구조체

  • 여러 자료의 항목을 모아 놓은 형태로써 서로 다른 여러가지의 자료형 데이터의 모음이다.
  • 구조체는 필드와 레코드로 이루어져 있다.

 

 

Def. 레코드

  • 서로 연관된 자료 항목이 모여있는 형태로 예를 들어 전화번호부를 확인하면 “음기”이라는 문자형 데이터와 “0109400”이라는 정수형 데이터가 있는데 { 이름, 전화번호 } 이렇게 연관된 자료 항목이 모여있는 형태를 레코드라 한다.

 

 

Def. 필드 ( = 아이템 )

  • 레코드를 구성하는 기본 단위로 여러 개의 서로 의미 있는 필드가 모여 하나의 레코드를 구성한다. 예를 들어 이름과 전화번호가 저장 되어있는 전화번호부에서는 이름이라는 필드와 전화번호 라는 필드 두개가 모여 하나의 레코드 ( 음기, 0109400 ) 이 만들어진다.

 

 

Def. 구조체 정의 및 구조체 멤버

  • 구조체를 선언하기 위해서는 우선 레코드의 멤버가 어떤 내용의 자료를 가지는지 즉 어떤 필드 값들을 가지는지 확인을 해야한다. 이를 구조체 정의라 하며 각각의 구조체를 구성하는 필드들을 구조체 멤버라 한다. 
  • Ex 구조체 멤버 ) 전화번호부 선언하기 위해서는 이름을 적는 칸과, 전화번호를 적는 칸이 있어야한다 즉 이름은 문자형, 전화번호는 실수형 이것을 선언하는 것이 구조체 정의, 각각의 전화번호부에 들어간 내용들 ( 음기, 0109400 ) 이것이 구조체 멤버가 된다.

 

 

5-1-2. 구조체의 정의

  • 구조체 정의는 구조체형만을 선언하거나 구조체형 선언과 함께 변수를 선언하는 형태로 정리한다.

 

형태

Struct 태그이름
{
구조체 멤버 선언;
} 이런 구조체형을 사용할 변수1변수2변수3 ….

 

 

Ex) 점의 좌표 구조체

Struct Point // 여기서 태그이름은 자료형의 이름 int, char 이런 거랑 비슷함
{
Int x=0;
Int y=0;
A, B, C 
l 구조는 아래를 보면 쉽게 이해 될것...
우리가 기존에 배웠던 자료형 선언
- Int a=0;
구조체 선언
- Struct Point {구조체의 구조} a=(1,3);
l 여기서 말하고 싶은 거는 구조체=자료형 이렇게 생각하면 된다

 

  • Struct라는 예약어는 구조체 정의를 위한 예약어로 자료형을 새롭게 정의하고 선언하겠다는 의미야 그래서 구조체를 한번 선언하면 나중에 아래에서 자료형은 struct + 태그이름으로 사용해서 기존 자료형처럼 선언해서 사용할 수 있어.

 

 

Def. 구조체 멤버 참조 연산자

  • 선언된 구조체 변수는 여러 개의 멤버를 가진다. 이때 각각의 멤버를 참조할때는 구조체 멤버 참조 연산자 ( . )을 사용해서 참조가 가능해 하는방법은 변수이름.멤버이름
  • Ex) {name, phonenum}의 구조를 가지는 구조체 변수 friend가 있다 하자 이때 friend라는 변수 속 name의 값을 참조하고 싶을때는 friend.name 이라고 하면 되는것이다.
  • 여기서 알수 있는 것은 구조체의 멤버를 참조할 때 멤버로 바로 접근한 것이 아닌 구조체 변수에서 참조연산자를 통해 접근을 하였다. 이 말은 즉 컴퓨터의 기억 장소에는 구조체 멤버 각각 기억장소가 할당되는 것이 아닌 구조체 변수에게 기억장소가 할당이 된다는 것이고 그 안에 멤버가 들어가는 것이다.
  • 즉 구조체의 기억공간의 크기는 각각 멤버들 크기의 합이다. 또한 멤버에 접근을 하고 싶으면 바로 할 수 없고 참조 연산자로 구조체 변수를 통해서 접근이 가능하다.

 

5-1-3. typedef를 이용한 구조체 정의

  • 구조체를 선언후 변수 선언을 할 때 마다 struct 태그이름 변수이름; 하기에는 프로그래밍이 너무 길어지고 복잡해진다. 이를 위해서 typedef라는 예약어를 통해 선언에 편리함을 주자

 

 

Def. Typedef

  • 이 예약어는 이미 정의되어 있는 내용을 다른 언어로 정의하는 역할을 한다. 즉 어떠한 예약어를 다른 말로 쓸 수 있게 해준다.

형태

Typedef 이미정의된이름 새로정의할이름;
Ex)
Typedef struct A A;
이러면 struct A a; // 구조체 A의 형식을 가지는 a
가 아닌 A a; 로 간편하게 사용 가능하다.

 

 

5-1-4. 구조체의 선언 위치 헤더파일 )

 

Def. 헤더파일

  • 우리가 함수를 적고 프로그래밍을 하는 곳은 소스 파일이다. 이때 프로젝트가 커지면 선언으로만 해도 엄청 길다. 이를 위해 헤더파일에 미리 변수들과 구조체를 선언해두어 별도로 관리해두면 편하다.
  • 헤더 파일에 내용을 모두 적은 후 소스파일에서 해더파일의 내용을 참조하기 위해서는 아래의 형식을 따르면 끝이다.

1)   C++프로그램 내에서 이미 정의된 헤더파일

Include <해더파일명>

2)   사용자가 직접 정의한 헤더파일의 경로가 현재 작업파일인 경우

Include “헤더파일명.h”

3)   사용자가 직접 정의한 헤더파일의 경로가 현재 작업파일이 아닌 경우

Include “경로명\\헤더파일명.h”

          

5.2 구조체 배열과 포인터

  • 먼저 구조체는 자료형과 동급이라는 것을 한번 더 상기하자. 각각의 자료형은 기억장소에 어떤 내용이 들어가는지에 따라 기억공간의 크기가 나눠져 있었고 그것은 포인터 연산에서의 기본 단위이다. 
  • 그러면 구조체에서는 위에서 확인했듯이 각각의 멤버들의 크기의 합이 구조체의 기억공간의 크기가 된다 또한 그것이 포인터 연산에서의 기본 단위이다. 
  • 즉 구조체의 배열을 선언하면 각각의 방은 구조체 크기만큼의 주소 값에 차이가 있어 만약 50바이트의 크기를 가지는 구조체는 배열의 주소 값 차이는 50바이트가 될것이다.
  • 여기서 중요한 것은 포인터 연산에서는 자료형의 기본크기가 기본단위가 된다는 것이다.
  • 즉 배열에서 배열의 이름이 배열의 시작 주소인데 여기서 +1을 하면 1바이트가 커지는 것이 아닌 배열의 자료형의 기본크기만큼 커지면서 다음 방의 주소 나타내게 된다.

 

1) 구조체 배열의 선언 방법

Struct 태그이름 배열이름[첨자];

 

2) 구조체 배열의 멤버 참조 방법

배열이름[첨자].멤버

 

3) 구조체 포인터 변수의 선언 방법

Struct 태그이름 *포인터변수이름 = &구조체변수

 

4) 구조체 포인터 변수의 간접연산자 사용 방법

(*구조체형 포인터 변수).멤버
구조체형 포인터 변수 -> 멤버

열혈강의 C++ 언어본색 책을 참고하여 작성한 글입니다.

 

CHAPTER 4. 고급변수 사용 포인터, 메모리

 

4.1 포인터 변수

  • 포인터는 기억 장소의 주소를 의미한다.
  • 이번 장에서는 일반 변수와 포인터 변수의 쓰임새를 정확히 구별할 수 있어야 한다.
  • 일반 변수는 자료 자체를 저장하기 위해 사용하고, 포인터 변수는 일반 변수가 실제 메모리에 할당된 주소를 참조하기 위해 사용한다.

 

 

변수 및 디버깅 단축키

  • 변수는 사용 전 미리 선언 해야한다.
  • 변수 선언에서 프로그래머로서의 예의 있는 코딩은 변수 초기화이다.
  • 변수 초기화를 잊어버리고 디버깅을 실행하면 아무리 살피고 살펴도 틀린 구석을 찾아내기 쉽지 않다.
  • 이때 프로그램 한줄 한줄 디버깅 모드로 실행 상태를 확인하면 초기화를 하지 않은 부분이 보일 것이다.

 

디버깅 모드에서 기본적으로 사용하는 단축키

단축키 설명
F5 디버깅을 시작
Shitf + F5 디버깅을 중지
F9 현재 커서 위치에 중단점을 설정하거나 해제한다.
F10 프로시저 단위로 디버깅을 실행
F11 한 단계씩 코드로 디버깅을 실행

 

 

Def . 포인터 변수

  • 포인터는 말 그대로 주소이다. 변수가 선언되면 기억장치 어딘가에 임의 공간이 할당된다. 그 할당된 공간은 주소로 식별된다. 바로 그 주소를 포인터라 한다.

 

 

주소지정 연산자 (&)의 활용 방법 // 변수의 주소를 확인하는 방법

Cout << “a의 주소 = “ << &a << Endl;

&를 사용하면 cout시 해당 변수에 할당된 주소를 가져온다

 

 

 

 

간접지정 연산자 (*)의 활용 방법  // 포인터 변수 선언 방법

자료형 *포인터 변수 이름;
  • 간접지정 연산자를 표시한 것 외에 일반 변수와 외형은 같다. 그리고 포인터 변수도 자료형을 정해야 한다.
  • 자료형은 주소에 저장된 값의 자료형에 따라 결정된다. 따라서 주소에 저장된 값의 자료형과 동일하게 포인터 변수의 자료형을 결정해야 한다.
  • 간접지정 연산자 (*)는 현재의 값을 메모리 주소로 하여 해당 기억 장소에 한 번 더 접근하게 한다.
  • 이는 직접 한 번에 접근한 것이 아닌 *로 지정된 포인터 변수를 거쳐 접근하기 때문에 간접 접근이라 한다.
출력 시 나오는 값들 예시
일반변수 -> Cout << a;
결과 : 값
&일반변수 -> 주소 Cout << &a;
결과 : 주소
포인터 변수 -> 주소 Cout << pa;’
결과 : 주소
*포인터 변수 -> 주소 Cout << *pa;
결과 : pa 주소를 참조하여 저장되어 있는 값을 불러옴

 

4.2 배열

Def . 배열

  • 배열은 연속적인 기억 공간을 나타낸다. 변수는 하나의 기억공간을 사용하는 반면 배열은 여러 기억 공간을 사용해 편리하다. 
  • 배열을 선언할 때는 하나의 이름에 몇 개의 기억 공간이 필요한지 그 개수를 정확히 적어야 한다. ( 변수를 사용해서 갯수를 적을수 없다. 정확한 숫자가 필요함 )

 

형태

자료형 배열이름[공간개수];
  • 배열은 선언이 되면 선언된 이름으로 자료형 기억장소 n개를 가지게 되는것이다.
  • 이때 각 기억 장소는 대괄호([])안에 숫자로 나타내고 이를 첨자라 한다.
  • 배열의 첨자는 0부터 시작한다. 즉 각각의 기억장소 이름은 배열이름[0], 배열이름[1], 배열이름[2] …… 이렇게 선언이 된다.

 

배열의 주소

  • 기본적으로 Window Xp가 32비트 운영체제이므로 작업 기본단위가 4바이트이다. 따라서 배열 변수의 주소 또한 4바이트 단위로 증가한다.
  • 배열 변수가 갖는 특징은 하나의 이름으로 여러 개의 기억 장소를 지칭할 수 있어 편리하다는 점이다. 그리고 또한 배열 이름이 주소를 나타내는 점이다. 예를 들어 score[30]이라고 배열을 선언하면 score은 배열의 시작 주소를 나타내는 포인터가 된다.
  • 또한 만약 배열 자료형의 기본 크기가 4바이트이면 배열 이름에 +1을 하게 되면 4바이트가 증가하게 되어 배열의 그 다음 요소의 주소를 나타내게 된다.
Cout << 배열이름 << Endl; 배열의 시작 주소 출력
Cout << &배열이름[0] << Endl; 배열의 시작 주소 출력
Cout << *(배열이름+n-1) << Endl; 배열의 n번째 요소에 저장된 값 출력
Cout << 배열이름[n-1] << Endl; 배열의 n번째 요소에 저장된 값 출력

 

정수형 배열

정수형 배열의 선언 및 초기화 방법

Int score[3] = {80,90,100}; 첫번째부터 순서대로 80,90,100의 값을 가진다.
Int score[30] = {100,} 첫번째는 100이고 나머지 배열의 요소는 0의 값

 

4.3 문자열

Def . 문자열

  • 문자열은 문자의 모음이다. 문자열을 사용하는 경우에는 문자들이 연이어 있는 자료에서 각각의 문자들에 대한 작업이 필요할 때 사용하면 편리하다.
  • 문자 변수의 자료형은 char이고, 문자 상수는 작은따옴표(‘’)로 표기하며 기억장소 1바이트를 차지한다. 문자열은 문자 상수의 모음으로 표기할 때 큰따옴표 (“”)로 표기한다.
  • 문자열의 특징 중 하나는 문자열의 마지막을 나타내는 문자 ‘\0’ (null)문자가 꼭 배열의 마지막에 들어간다. 예를 들어 computer이라는 문자열을 선언하면 배열의 9번째 요소는 null문자이다.

 

 

문자열의 선언 및 초기화 방법

Char string[30] = {‘c’, ‘o’, ‘m’, ‘p’, ‘u’, ‘t’, ‘e’, ‘r’ ‘\0’ } 1~8번째 요소에 문자 9번째 null
Char string[30] = “computer” 위와 같다
Char string[3] = “computer” 범위 초과로 인한 오류 발생

 

 

문자 배열의 활용과 주의점

  • 숫자 데이터와 마찬가지로 문자열도 숫자에서의 연산과 같이 요구되는 기능이 있다. 주로 많이 사용되는 것은 문자열 전체 복사나 일부분 복사, 문자열 내에서 특정 문자 찾기 등이 있다.
  • 이런 기능들은 표준 라이브러리 iostream에 이미 정의 되어있다.

 

문자열 관련 함수들

  • 여기서 const char* _str[ 아래에서 str이라고 표시 ] 은 y=f(x)값에서 x라고 생각하면 됨 
  • Char* _Dest [ 아래에서 dest라고 표시할게 ] 는 y=f(x)에서 y값이라고 생각하면 됨 
함수 설명
Countof(str) 문자열 str의 배열 크기 구하기
Ex) score[30]을 이 함수에 넣으면 30이 출력
Strlen(str)
// string length
문자열 str의 길이 구하기
Strcpy(dest,str)
// string capy
문자열 str을 dest에 복사!
Dest에 있는 내용 지우고 str에 있는 내용 복사
Strncpy(dest,str,count)
// string n capy
문자열 str의 내용 count만큼 dest에 복사!
Dest에 있는 내용 지우고 str에 있는 내용 n개 복사
Strcat(dest,str)
// string concatenate
문자열 str의 내용 dest에 붙이기
Dest에 있는 내용 살리고 그 뒤에 str 내용 붙이기
Strncat(dest,str,count)
// string n concatenate
문자열 str의 내용 count만큼 dest에 붙이기
Dest에 있는 내용 살리고 그 뒤에 str 내용 n개 붙이기
Int strcmp(str1,str2)
// string compare
문자열 str1str2를 비교하여 결괏값을 반환,
결괏값을 -1,0,1중 결정
Str1<str2, str1=str2, str1>str2
이때 문자열 내용을 16진법으로 변환 후 값 비교

위에서 노랑색으로 칠해진 함수들은 보안에 취약한 함수이다. 이것들을 사용해 디버깅을 실행하면 경고 창이 나올 것이다.

 

보안에 취약하지 않은 함수들 ( 그냥 위에 함수에 _s만 붙임 )

함수 설명
Strcpy_s(dest,size,str)
// string capy
문자열 strdest에 복사!
Dest에 있는 내용 지우고 str에 있는 내용 복사
이때 복사되는 문자배열의 최대 크기는 size
Strncpy_s(dest,size.str,count)
// string n capy
문자열 str의 내용 count만큼 dest에 복사!
Dest에 있는 내용 지우고 str에 있는 내용 n개 복사
이때 복사되는 문자배열의 최대 크기는 size
Strcat_s(dest,size,str)
// string concatenate
문자열 str의 내용 dest에 붙이기
Dest에 있는 내용 살리고 그 뒤에 str 내용 붙이기
이때 붙여지는 문자배열의 최대 크기는 size
Strncat_s(dest,size,str,count)
// string n concatenate
문자열 str의 내용 count만큼 dest에 붙이기
Dest에 있는 내용 살리고 그 뒤에 str 내용 n개 붙이기
이때 붙이지는 문자배열의 최대 크기는 size

 

 

4.4 포인터 : 메모리 주소

 

포인터 변수는 기억장소의 주소를 기억하기 때문에 주어진 크기는 운영체제에 의해 결정이 된다. 즉 윈도우 테는 32비트를 기본으로 하기 때문에 기억 장소를 나타내는 주소는 모두 4바이트가 할당된다.

포인터 변수는 저장하는 주소의 자료형과 서로 일치해야 한다.

정수형, 문자형, 실수형, 배정도형 포인터의 크기는 4byte이다. 즉 이 자료형들의 포인터를 1증가하면 그 다음 방의 주소가 출력이 된다.

 

 

 

4.5 레퍼런스 변수

 

Def . 레퍼런스 변수

  • 레퍼런스 변수는 이미 선언된 변수를 다른 이름으로 부르는 변수이다.
  • 따라서 레퍼런스 변수는 변수 선언에서 반드시 어떤 변수를 다른 이름으로 부르는가를 명시해야 한다.
  • 즉 반드시 초기화가 함께 이루어져야 한다.
  • 이때 선언 시 주소지정 연산자(&)를 사용한다.

 

 

레퍼런스 변수의 선언 및 초기화 방법

자료형 &변수이름 = 변수;

레퍼런스 변수를 사용하면 포인터 변수와 같이 같은 기억 장소를 다른 이름으로 참조할 수 있는데, 포인터 변수는 간접접근이지만 레퍼런스 변수는 직접 접근을 통해 참조한다.

 

 

 

4.6 동적할당

 

Def . 정적 & 동적 할당

  • 기억 장소를 할당 하는 방법에는 정적할당과 동적할당이 있다.
  • 프로그램 실행 전에 필요한 기억 장소를 미리 할당 하는 방법을 정적, 실행 중 필요한 만큼 기억장소를 요청하는 것이 동적할당이다.

 

동적할당을 이용한 변수 선언 방법

자료형 *포인터변수 = new 자료형[개수]
Ex ) int *pi = new int[30]

만약 필요한 변수의 개수가 하나이면 [ ]내용은 생략한다.

 

 

 

 

동적할당을 이용한 변수 선언 해제 방법

Delete 포인터변수;  // 하나의 기억장소 해제 시
Delter [] 포인터변수;  //  여러 개의 기억장소 해제 시

여러 개 해제시 [ ] <- 여기안에 숫자 쓸 필요 X

 

 

정적할당과 동적할당의 차이

  할당 방법 할당 장소 기억장소 확보 시기 기억장소 해제 시기
정적 할당 필요한 자료형 변수 선언 스택(stack)
함수 선언후 {} 여기 안에서만 할당
변수가 선언된 함수가 호출될 떄 변수가 선언된 함수가 실행이 종료될 때
동적할당 New 연산자 사용 (heap)
함수 상관없이 모든 곳에서 할당
동적 할당 코드가 실행될   Delete 명령이 실행될 때
만약 명령이 없으면 프로그램이 종료될 때
  • 위에 표를 확인하면 동적할당은 delete명령이 없으면 프로그램 내 모든 곳에서 기억장소를 확보하고 있다.
  • 그러므로 꼭 사용이 끝나면 delete명령으로 해제를 시켜야 한다. 만약 해제를 안시키면 다른 곳의 변수이름과 겹칠 때 오류가 생긴다.

 

 

열혈강의 C++ 언어본색 책을 참고하여 정리한 글입니다.

 

CHAPTER 3. 조건문, 반복문, 네임스페이스

 

3.1 조건문 if  // 주로 조건이 범위일경우

Def . If

  • 기본 if문은 주어진 조건이 참일 경우에만 내용을 실행한다. 그렇지 않으면 실행을 안하고 넘어가게 된다.

형태

if( 조건 {
           실행할 내용
}
  • 수행할 내용이 한문장이 넘으면 반드시 중괄호 {}를 사용해야 한다. 만약 한문장이라면 { }는 사용할 필요가 없다.

 

 

만약 거짓일 경우에 다른 무언가를 실행해야 할 때는 어찌 해야 할까?

 

 

Def . If ~else

  • 위에서 배운 if문은 오직 조건이 참일때만 시행하는 반면 if ~else문은 거짓일때도 수행할 문장을 지정할 수 있다. 이 문장은 경우의 수가 오직 두가지 일 경우 사용한다.

형태

if( 조건 ) {
   조건이 참일 경우 실행할 내용
}
else  // 여기서 else에 대한 조건은 필요 없다 그냥 if의 조건을 만족시키지 못하면 else를 수행하게 된다.
{
   조건이 거짓일 경우 실행할 내용
}

 

 

Def . if ~else if ~ else

  • 위에서 배운 if ~ else문은 if가 거짓이면 모두 else로 들어간다. 즉 경우의 수가 두가지인 경우일 때 사용하는데 만약 경우의 수가 여러가지이면 if ~ else if ~ else 문을 사용한다.

형태

if ( 조건1 )
{ 수행할 내용 }
else if ( 조건2 )
{ 수행할 내용 }
else if ( 조건3 )
{ 수행할 내용 }
else // 위의 조건들 모두 부적합 할 때 시행
{ 수행할 내용 }
  • 이 행태는 그냥 위에서 배운 else에다가 다시 if-else문을 반복적으로 사용해도 되는데 그건 코드의 길이가 길어지고.. 가독성이 너무 안좋아진다.
  • 주의할점은 조건 1~3까지를 동시에 확인하는것이 아닌 위에서부터 순서대로 조건을 확인해서 참이면 바로 아래는 생각 안하고 수행해버리니깐 조건 잘 설정해두자.
  • 코드 만들때 그럴일은 많이 없겠지만 조건확인 순서에 따라 결과가 달라질수도 있다.

 

 

3.2 상수 조건문 switch ~ case // 조건이 상수 값 하나 일 경우

Def . switch ~ case

  • 조건이 범위 형식으로 나오는 3.1의 if문과 달리 switch는 조건의 결과가 상수 값 하나 일 경우 사용한다. 즉 a=1일경우, a=2일경우 등등 이럴 경우 사용한다
  • 예를 들면 주사위를 굴린다 생각해보자 결과는 1~6 상수값이다.  if문으로 해결할수는 있지만 이럴 경우 switch case문이 좀더 코드 가독성이 더 좋다.

형태

switch( 조건문 )
{
case 조건결과1 :
     조건 결과가 조건결과1일 경우 수행할 내용;
case 조건결과2 :
     조건 결과가 조건결과2일 경우 수행할 내용;
default :
     모든 조건이 맞지 않을 때 수행할 내용;
}
  • 이때 주의해야 할 점은 조건문의 결과가 조건결과1일경우 조건결과1 이하의 모든 내용이 수행이 된다. 비슷하게 조건결과2일 경우 조건결과2 이하의 모든 내용 즉 조건결과 3, ..... default 모두 수행이 됨.

 

Def . break

  • 위에서 배운 switch ~case는 결과에 따라 수행내용이 한가지가 아닌 결과에 대한 수행내용 그리고 그 이하의 내용이 모두 수행이 된다. 이를 해결하기 위해 break라는 연산자를 통해 주어진 범위에서 벗어 나야 한다. 즉 이제 수행내용을 그만하고 싶을 때 사용!

형태

switch(조건문)
{
case 조건결과1 :
      조건 결과가 조건결과1일 경우 수행할 내용;
      break;
case 조건결과2 :
      조건 결과가 조건결과2일 경우 수행할 내용;
      break;
default :
      모든 조건이 맞지 않을 때 수행할 내용;
}

주의 할 점은 default에는 break를 쓸 필요가 없다. 왜냐면 어짜피 마지막 이니깐 

 

 

 

여러 case에 대해 같은 내용을 수행하고 싶으면 밑의 형태를 사용할수도 있다.

switch( 조건문 )
{
case 조건결과1 :
case 조건결과2 :
     조건 결과가 조건결과1 또는 조건결과2일 경우 수행할 내용;
     break;
default :
     모든 조건이 맞지 않을 때 수행할 내용;
}

이렇게 하면 조건결과 1일 경우에는 아무것도 없으니 수행 안하고 break가 없으니 조건 결과2 를 수행하게 되고 조건결과 2는 당연히 수행하고 break를 만나 빠져나가게 된다.

 

 

 

3.3 반복문 For, while, do~while

  • 같은 내용을 여러 번 실행해야 하면 반복문을 사용하여 번거로움을 피하자!
  • 반복문에는 반복횟수가 정확하게 정해질 경우가 있지만 그렇지 않은 때도 있다.
  • 예를 들어 입력한 데이터 값이 100이하인 경우 또는 반복 여부를 프로그램 사용자가 직접 입력해서 결정 하는 경우 등이 있을 수 있다.

 

반복문의 필수 요소

  • 1. 무엇을 반복할 것인가?( 제어변수 또는 반복변수)
  • 2.  어떤 조건일 때 반복할 것인
  • 3. 반복할 내용은 무엇인가?
  • 4. 반복하면서 제어변수에 대한 변화는 있나?

 

Def . For

  • for문은 반복문의 횟수가 정해져 있을 때 반복과 관련된 내용을 나타낼 수 있다.

형태

for( 제어변수 초기화 ; 조건문 ; 증감문 )
{
   반복할 내용;
}

반복문 for의 실행 순서는 아래와 같다

  1. 제어변수를 초기화 한다.
  2. 조건문을 실행한다. 참일 경우 반복할 내용을 시행하고 거짓일 경우 반복문 밖으로 제어가 이동한다.
  3. 반복할 내용을 시행한다.
  4. 증감문을 실행하고 다시 조건문을 실행한다.

 

for은 만약 제어변수가 처음부터 조건문에 대해 거짓일 경우 바로 반복문 밖으로 나가 즉 반복할 내용을 한번도 수행 안 할 수가 있어!

 

  • 여기서 주의할 점은 만약 초기화가 되어있지 않거나 반복 여부를 묻지 않는다면 영원히 끝나지 않는 무한 반복을 시행하게된다.
  • 초기화는 뭐 for 위에서 해도 되고 증감문은 반복할 내용안에 넣어도 상관 없다
  • 대신 조건문은 꼭 들어가야한다.

 

방금 서술한 형식의 형태는 이렇게 된다.

제어변수 초기화;
for( ; 조건문 ; )
{
   반복할 내용;
   증감문;
}

 

Def . while

  • while문은 바로 위에 있는 for문에서 초기화를 미리 시행하고 증감문 또한 반복내용에 포함된 형식이다. 진짜 for문과 엄청 비슷한데 왜 있냐면 그냥 프로그램 제작자의 가독성을 편리하기위해 for 또는 while 둘 중 하나 사용 하는거야

 

형태

제어변수 선언
while(
조건문)
{
   반복할 내용;
   증감문;
}

이때 주의할 점은 꼭! 제어변수가 while문 이전에 선언 되어 있어야 하고 초기화 되어 있어야한다. 그리고 증감문도 반복할 내용에 들어가 있어야 한다. 형태는 위에서 설명한  특이한 for문의 형태와 같다.

 

While도 마찬가지로 제어변수가 조건에 맨처음부터 거짓이면 반복할 내용을 한번도 수행 안한다.

 

 

 

Def . do ~ while

  • 위에서 설명한 for, while문은 조건에 대해 맨처음부터 거짓이면 내용을 한번도 수행 안해 대신 do ~ while문은 무조건 한번은 수행한다음에 조건에 대해서 생각을 한다.
  • 주로 범위 (조건) 에 맞는 내용을 입력 받아야 할 때 do ~ while문을 사용하는게 편리하다.
  • 예를들어 나이를 입력 받고자 할때 우선 한번 입력 받고 그다음 조건 판단후 만약 이상한 값이 들어오면 반복해서 조건을 만족시킬때까지 나이를 입력 받는 문장을 수행한다.

형태

제어변수 초기화
do

{
     반복할 내용;
     증감문;
} while (조건문)

필요에 따라 증감문은 안써도 될때가 있다.

 

 

Def . continue

  • continue 명령문은 반복 범위 처음으로 실행 제어를 이동하게 한다.
  • 비슷하게 break는 반복 범위에서 나가게 하지만 continue는 처음으로 가는게 차이다. 즉 반복은 계속 하고싶은데 조건 내에서 어떤거는 또 수행 안하고싶다면 사용한다.
  • 즉 이거를 통해 조건 내에서도 어떤 경우에는 내용을 실행 안하고 어떤 경우에는 내용을 실행할수도 있다.

예시

for(i=1;i<10;i++)
{
   if (i%2==0)
       continue;
   cout << " i =  " <<  i << endl;
}

이렇게 하면 짝수일 경우에는 cout 이 되기 전에 다시 증감문으로 실행 제어가 이동을 하게 되어 짝수가 출력이 안된다.

 

 

3.4 반복문의 중복

  • If 문안에 또다른 if문도 쓸 수 있는것과 같이 반복문에서도 for, while, do~while안에 for, while, do~while을 사용 할 수가 있다.
  • 이때 주의할 점은 반복 횟수를 결정하는 제어 변수의 사용인데 실행 범위가 제어 변숫값 변화에서 명확해야 한다는 것이다.
  • 이부부은 직접 해보면서 배워야한다..
  • for문은 반복 쉬운데 while이나 do~while을 반복해서 사용하는거는 쉽지 않을거 같다.
  • 사실 코딩하는 사람마다 취향이지만 나는 while문보다 for문을 즐겨 사용한다.

 

3.5 코드 범위와 네임스페이스

  • 위에서 배웠듯이 어떤 내용을 실행할때는 그 내용의 범위가 있다. for문의 범위, if문의 범위 등등 모두 { } 를 통해 범위를 표시한다.
  • C++프로그램은 파일 단위 그리고 범위 단위에서 크게 선언부( 네임스페이스를 선언하는 부분 )와 동작부( 예시로는 main함수의 범위 )로 구분이 되고있다.
  • 프로젝트 내에는 같은 이름의 함수가 사용될수 없다. 즉 int main() <-이거는 main이라는 함수의 내용이다 라는 의미이고 int main2() <-이거는 main2라는 함수의 내용이라는 것이다. 같은 이름의 함수가 두개 있을 수는 없다.
  • 한 범위 내에서 변수를 선언하면 그 범위 내에서만 그 변수를 사용할수 있어 즉 for문 안에서 int a=200이라고 초기화하고 선언했다 하자 그럼 for 밖에서는 a=200이 아닌거다.  ( 코딩하다보면 이런 실수를 많이 하게됨.. )

 

 

Def . namespace

  • 네임스페이스는 말 그대로 소속을 알리는 역할이다.
  • 즉 네임스페이스를 선언부에서 선언할텐데 각각의 공간에 특정한 변수가있는데 동작부에서 따로 변수 선언을 할 필요없이 네임스페이스를 불러와서 변수를 사용할 수가 있게된다.

 

형태

namespace 이름 
{
     선언내용; //  변수 선언
}

 

 

 

그리고 동작부에서 namespace에 있는 선언 내용을 가져와서 사용하고 싶을떄는 아래 형태를 사용하면 되는거야

네임스페이스이름::네임스페이스안에있는변수
 
예시 )
Namespace gisan
{ int a=200; }
 
……
 
Cout << “namespace gisan a= “ << gisan::a << Endl;
 
이렇게 하면 gisan이라는 네임스페이스의 a200으로 초기화 되어있으니 200이라는 숫자가 출력이 된다.

 

 

이렇게 :: 쓰는게 귀찮잖아 솔직히 그럴 때 사용하는게 using namespace 이름; 이거야 우리가 계속 접했는 using namespace std; 여기서는 cout, cin, Endl 등 이런것들이 std라는 네임스페이스에 있던 것들이고 원래는 std::cout, std::cin, std::Endl 이렇게 사용했어야 하는것들이지

 

형태

선언부에 이 한문장을 입력해주면 된다.
using namespace 이름;

 

 

 

근데 여기서 문제가 있어 using 지시자를 사용할 경우 다른 네임스페이스에 같은 이름의 필드가 있을 때는 주의해야한다.

이럴경우에는 그냥 그 필드를 언급할때만 ::사용하면 끝이다.

 

형태

Namespace gisan
{ int a=200; }
Namespace eom
{ int a=100; }
……
Cout << “gisana<< gisan::a << Endl;
Cout << “eoma<< eom::a << Endl;

 

열혈강의 C++언어본색 책을 보면서 정리한 자료입니다.

 

CHAPTER 2. 자료형과 연산자

 

2.1 변수와 상수

 

Def . 프로그래밍

         자료를 저장하고 더하거나 비교하는 등의 연산을 하여 자료를 처리하는 과정.

         프로그래밍의 기본은 자료형과 연산자들이다.

 

Def . 변수

         프로그램이 처리한 처리대상 또는 처리 결과를 저장하는 주 기억장치의 특정 위치

 

변수는 이름을 지정할 때 특정 규칙들이 있다.

  • 영문 소,대문자, 숫자, 밑줄(_)으로만 이름을 지정 가능 // 띄어쓰기 불가능
  • 숫자는 변수 이름의 첫 글자에 들어갈수 없다
  • 영문 소문자와 대문자는 구별이 된다
  • 예약어는 변수 이름으로 사용 불가능 // 예약어 : 컴퓨터 언어에서 이미 약속된 단어
  • 변수 이름 길이에는 제한이 없다

 

-      프로그래밍을 할 때는 우리가 사용하는 일반적인 단어로 하는 것이 아닌 컴퓨터의 언어로 진행을 해야 한다. 이때 사용하는 단어는 크게 두가지 이다. 예약어사용자 정의어로 구분이 된다. 예약어는 이미 컴퓨터 언어에서 약속된 단어이고 사용자 정의어는 말 그대로 사용자가 필요에 의해 정하는 것으로, 예약어는 사용자 정의어로 사용할 수 없다. 변수는 사용자 정의어에 해당이 된다.

 

 

Def . 상수

  • 기억 장소에 저장되는 값으로 변수에 저장될 수도 있고 프로그램 코드 내에서 별도의 변수 할당 없이 사용될 수도 있다.
  • 상수의 종류에는 문자와 숫자로 나누어진다. 숫자는 일반적인 표기법을 따르지만 문자의 경의 작은따옴표(‘’)로 묶어서 표기하고 문자열은 큰따옴표(“”)로 묶어서 표기한다.

 

Def . 선언

  • 변수를 사용하기 전에 이를 알리는 작업이다. 변수가 어떤 종류의 데이터를 가지는지 유형을 설명하는 작업이다.

 

 

2.2 컴퓨터가 표현하는 데이터

  • 프로그램을 작성할 떄 가장 먼저 해야 할 일은 대상 데이터를 저장할 변수와 저장되는 데이터의 성격을 결정하는 것이다. ‘성격’이란 데이터 특성에 따른 컴퓨터의 표현이나 저장 방식으로, 숫자인가 문자인가 또는 숫자라면 소수점이 있는 형태인가 아닌가 등을 구분하는 것이다.
  • 기억해야 할 것은 문자는 (‘’) 또는 (“”)로 묶어서 표기했다는 것이다.

 

Def . 자료형 ( 데이터 형 Data Type )

         데이터 특성에 따른 컴퓨터의 표현이나 저장 방식을 설명하는 형식

 

 

아래 표는 C++에서의 대표적인 자료형의 예약어다.

표기 내용 크기
Char 문자 1Byte = 8Bit
Double 배정도형 실수 8Byte = 64Bit
Float 단정도형 실수 4Byte = 32Bit
int 정수 ( 컴퓨터 언어에서의 기본! ) 4Byte = 32Bit

 

  • 자료형간의 연산 결과

         같은 자료형의 연산 = 같은 자료형의 결과를 얻는다.

         서로 다른 자료형의 연산 = 기억장소 크기가 더 큰 자료형의 결과를 얻는다.

         즉 컴퓨터 자료형에 따라 데이터의 표현 방법과 연산 결과가 달라진다.

 

 

2.3 기본 자료형

  • 컴퓨터 언어의 변수도 데이터 담을 수 있는 크기가 있다. 그 범위를 넘으면 정확한 값을 표현하지 못한다. 즉 변수의 크기에 따라 사용할 자료형이 구분이 된다.
표기 내용 크기 예시
Char 문자 1Byte = 8Bit ‘A’
Unsigned char ??????? 1Byte = 8Bit ???????
Double 배정도형 실수 8Byte = 64Bit +-3.54326
Long double 긴 배정도형 실수 8Byte = 64Bit +-3.543154743
Float 단정도형 실수 4Byte = 32Bit +-7467.1
int 정수 ( 컴퓨터 언어에서의 기본! ) 4Byte = 32Bit +-984
Short int 짧은 정수 2Byte = 16Bit +-45
Long int 긴 정수 4Byte = 32Bit +-5643
Unsigned int 부호 없는 정수 4Byte = 32Bit 872
Unsigned short int 부호 없는 짧은 정수 2Byte = 16Bit 43
Bool 논리형 연산자 1Byte = 8Bit 1(true), 0(false)

주의 해야 할 점은 소수점이 있는 상수는 배정도형 실수 (Double) 을 기본으로 한다. 즉 선언을 안 해도 자동으로 Double로 인식

 

 

2.4 변수의 자료 범위

  • 변수의 크기에 맞지 않은 자료를 입력하면 에러가 아닌 화면에 예상치 못한 값이 나온다.
  • 최대값을 넘는 경우 다시 최솟값부터 진행이 된다.
  • 해당 변수가 다룰 데이터의 범위가 적절한지를 꼭! 잘 판단해야 한다. 이를 해결하기 위해 형 변환이라는 작업이 있다.

 

 

2.5 형변환

  • 정수형 값은 배정 도형 변수(double, float)에 할당이 가능하다. 따로 형 변환 필요 없이 가능은 하지만. 결과는 정수형의 결과를 실수형으로 표현한 데이터가 손실되어 표현된다.
  • 즉 a=3, b=20 / float = c  여기서 c=b/a 를 진행하면 c=6.00000이 표현된다.
  • 이러한 현상을 대비하기 위해 우리는 형 변환이 필요하다.
  • 즉 오른쪽의 수식 결과를 왼쪽의 변수 자료형에 맞게 변환 작업을 하는 것이다.
  • 방법은 그냥 c=b/(float) a 또는 c=b/af이라고 언급하면 끝이다.

 

Def . 명시적 형변환 ( Type Conversion )

  • 일시적으로 형을 변환시키는 방법이다. 즉 수식 결과를 변수 자료형에 맞게 일시적으로 수식을 변환시키는 방법!

 

2.6 연산자

2.6.1 입출력 연산자

표기 내용 예시
Cout 출력 연산자 Cout << 출력내용;
Cin 입력 연산자 Cin >> 입력내용;
  • 리다이렉션 기호인 <<, >> 이것들은 입출력 방향을 전환하라는 말이다. << 기호는 오른쪽의 내용을 왼쪽 장치로 입출력 방향을 결정한 것이다. 즉 cout << “메롱”; 은 cout 장치로 메롱을 보내라는 내용이다.

 

2.6.2 산술 연산자

표기 내용 예시
* 곱하기 3*6
/ 나누기 3/6
+ 더하기 3+6
- 빼기 3-6
% 나머지를 구하는 연산자 3%2
  • 산술 연산자는 이항 연산자 ( 두개의 연산대상을 필요로 하는 연산자 ) 이다.

 

 

 

2.6.3 변수 초기화와 단축 연산자

 

Def. 변수 초기화 ( initialization )

  • 특정 변수에다가 값을 넣어 주는 작업이다. 즉 데이터를 넣어주는 작업이다.
  • 이때 주의해야할 점은 변수 속에 이전에 사용했던 데이터 즉 쓰레기 값이 남아 있는데 연산자를 통해 명령을 수행한다면 ( ex. A+1 / 이때 A는 초기화 X ) 에러가 나온다.

 

 

 Def. 단축 연산자

  •    누적 연산 수식을 간략하게 표현하기 위해 사용하는 연산자
표기 내용 예시
*= 곱셈 누적 A*=3 : A3을 곱한다.
/= 나누기 누적 A/=3 : A3을 나눈다.
+= 더하기 누적 A+=3 : A3을 더한다.
-= 빼기 누적 A-=3 : A3을 뺀다.
%= 나머지 누적 A%=3 : 3의 나머지 구한다
++ 1 누적 A++ : A1을 더한다
-- 1 감소 A--  : A1을 뺀다
  • 이때 ++ 와 – 연산자는 변수의 앞에 올 수도 있고 뒤에 올 수도 있다. 앞에 오는 경우 즉 ++가 전치 연산자가 되는 경우에는 변수 사용 전 1을 더하는 작업을 진행한다.  뒤에 오는 경우 즉 ++가 후치 연산자가 되는 경우에는 변수 사용 후 1을 더하는 작업을 진행한다.

 

 

2.6.4 논리형 그리고 관계 연산자, 논리 연산자

  • 우리가 앞서 배운 자료형에는 논리형이라는 것이 있다. 대표적으로 bool이 있는데 이 자료형은 데이터를 true, false 즉 1과 0으로만 표현을 한다. 그렇다면 자료형 범위는 1Bit가 충분하다. 하지만 컴퓨터 자료표현은 1Byte로 이루어지기 때문에 크기는 1Byte가 된다.
표기 내용 크기 예시
Bool 논리형 연산자 1Byte = 8Bit 1(true), 0(false)

여기서 Bool0이 아닌 자료는 모두 true로 표현한다.  ( 컴퓨터 구조 수업을 들으면 그 이유를 알수있음.. )

 

 

Def. 관계 연산자

  •    산술 연산자 외에 ‘크거나 같다’와 같이 크기를 비교하는 연산자
표기 내용 예시
>, < 크다, 작다 10>3 : 결과는 true
>=, <= 크거나 같다, 작거나 같다 10>= 10 : 결과는 true
== 같다 ( = 하나만 쓰면 할당의 의미 ) 10==9 : 결과는 false
!= 다르다 10!=10 결과는 falsa

 

Def. 논리 연산자

  •    두개 이상의 연산 결과에 대해 연산 결과 간의 관계에 대한 논리를 판단하는 연산자
표기 내용 예시
&& 논리곱 (AND) 조건의 결과가 같아야 true (10>3)&&(10<3) : 결과는 false
|| 논리합 (OR) 조건중 하나만 true true (3>10)||(10>3) : 결과는 true
! 논리 부정 (NOT) 하나의 항목에 대해 연산을 수행하며 부정의 의미 !3 : 결과는 false
왜냐면 30이 아니므로 true인데 부정 false

 

2.6.5 비트 연산자

  • 컴퓨터의 자료 표현은 바이트 단위로 수행된다. 반면 비트 연산자는 연산 단위가 자료형에 상관없이 비트 단위(2진수)로 수행이 된다.
  • 비트 연산자를 사용할 때 자료 값 확인을 위해 2진법을 사용하게 되면 표현 자릿수가 길어지므로 16진법을 사용한다.
  • 비트 연산자가 필요한 이유는 컴퓨터의 기본 단위인 비트를 통해서 바로 연산을 이용해서 훨씬 빠르기 때문이다.

진법 표현

표기 내용 예시
HEX 16진법 출력 Cout << hex << a; : a16진수로 출력
Dex 10진법 출력 Cout << dex << a; : a10진수로 출력
0x 16진법 표기 0x1243 : 10진법의 1243이 아닌 16진법의 1243

 

비트 연산자

표기 내용 예시
>>  오른쪽 시프트 111>>2 : 1112진수로 나타내고 오른쪽으로 2비트 이동
<<  왼쪽 시프트 111<<2 : 1112진수로 나타내고 왼쪽으로 2비트 이동
& 비트 논리곱 비트 단위(2진수)로 논리곱 수행
| 비트 논리합 비트 단위(2진수)로 난리합 수행
^ 비트 배타적 논리합 (NOR) 비트 단위(2진수)로 배타적 논리합 수행
서로 다른값은 참, 같으면 거짓
~ 비트 논리부정 비트 단위(2진수)로 부정 수행
  • 이때 주의해야 할 점은 시프트 할 때 이동되어서 없어지는 부분도 있고 새로 추가되는 부분도 생긴다. 새롭게 생기는 부분에는 0으로 채워진다.
  • 또한 결과를 나타낼 때 32비트에서 0번째 비트 ( 2진수의 가장 앞부분 )이 1이면 음수이다.

 

2.7 연산자 우선순위

  • 연산자의 우선순위는 크게 산술 연산자, 관계 연산자, 논리 연산자 순이다. 비트 연산자의 경우 관계 연산자와 논리 연산자 중간에 위치하나 단항 연산자에 해당하는 ~는 산술 연산자보다 앞서 수행된다. 또한, 소괄호는 단항 연산자를 제외한 다른 연산자보다 우선된다.
  • 쉽게 이야기하자면 전치 연산자보다 후치 연산자가 우선적이며, 단항 연산자는 복항 연산자보다 우선적이다. 그리고 산술 <- 관계 <- 논리 순이다.

 

 

+ Recent posts