시험공부

(2025-2) Introduction to programming(2) 4. Expressions & Statements

norepinephrine 2025. 12. 18. 14:47

목표: C++의 연산자/표현식 의미, 문장 종류와 제어 흐름, 형 변환, 예외 처리를 시험에서 설명·코딩할 수 있다.


1) 연산자 훑어보기 (개요)

  • 산술/논리/관계/대입/증감/멤버접근/조건(?:)/sizeof/콤마/비트 연산자 구성을 한 단원에서 다룸.
  • 슬라이드 인덱스: 산술→논리·관계→대입→증감→멤버→조건→sizeof→콤마→비트 순서로 소개됨.

2) 논리/관계 연산자 & 단락 평가(short-circuit)

  • &&는 둘 다 true일 때만 true, ||는 하나만 true여도 true. 왼쪽 피연산자를 먼저 평가하고 결과가 결정되면 오른쪽은 건너뛴다(단락 평가). !는 부정. 결과는 bool.
  • 관계 연산(<, <=, >, >=)은 bool 반환, 좌결합.
// 오른쪽은 필요할 때만 평가됨
ptr && *ptr == 42;  // ptr이 nullptr이면 *ptr 평가는 생략(안전)


3) 대입(=)과 복합 대입

  • 대입 결과는 “왼쪽 피연산자(lvalue) 그 자체”이며 왼쪽의 타입을 가진다. 타입이 다르면 오른쪽이 왼쪽 타입으로 변환된다.
  • 우결합: a = b = 0;에서 b=0의 결과가 다시 a에 대입됨.
  • 우선순위 낮음: 조건식에서 대입을 쓰면 괄호로 분명히! (==와 = 혼동 주의)
int a, b;
if ((a = get()) != 0) { /* ... */ } // 괄호로 의도 명확히
a += 3; // 복합 대입


4) 증감 연산자(++/--) — prefix vs postfix

  • 전위형(prefix): 값을 바꾸고 바뀐 자신을 결과로 준다.
  • 후위형(postfix): 값을 바꾸지만 바뀌기 전 복사본을 결과로 준다. 필요할 때만 후위형 사용 권장.
  • 역참조·증감을 한 식에 섞을 때 우선순위에 주의((p++)는 OK). 피연산자 평가 순서가 미정일 수 있으니 복잡한 표현식은 피하자.
auto x = *it++;  // x에는 '증가 전' 원소 복사, it는 다음 원소로 이동


5) 멤버 접근 . / >

  • obj.mem은 객체의 멤버, ptr->mem은 포인터가 가리키는 객체의 멤버. (*ptr).mem과 동일. 역참조 의 우선순위가 .보다 낮아 괄호 필요할 수 있다.

6) 조건 연산자 ?:

  • 간단한 if-else를 표현식 수준에서 작성. 우선순위가 낮으므로 복잡한 출력문에서 괄호로 감싸는 게 안전.
cout << (score >= 60 ? "pass" : "fail") << '\\n';


7) sizeof

  • 피연산자(표현식/타입)의 바이트 크기 반환. 결과 타입은 size_t, 우결합. 피연산자를 평가하지 않는다(미초기화 포인터 역참조도 ‘평가’되지 않음).
  • 참조의 sizeof는 참조 대상 타입 크기, 배열은 전체 크기(원소크기 × 개수).

8) 콤마 연산자 ,

  • 왼쪽을 평가·버리고 오른쪽 값을 결과로 반환(좌→우 순서로 평가). 슬라이드 목록에 포함.
for (int i=0, j=n-1; i<j; ++i, --j) { /* ... */ }


9) 비트 연산자

  • 비트 켜기/끄기/토글 등의 예로 설명(비트 27 예시).
flags |= (1u << 27); // 켜기
flags &= ~(1u << 27); // 끄기


10) 형 변환 (implicit/explicit)

  • 묵시적 변환: 산술 혼합 시 공통 타입으로 승격/변환, 작은 정수형은 정수 승격. 조건식에서는 bool로 변환. 배열→포인터, 0/nullptr→임의 포인터 등 규칙 포함.
  • 명시적 변환(이름있는 캐스트): static_cast/const_cast/reinterpret_cast/dynamic_cast 소개. const_cast는 low-level const만 제거. reinterpret_cast는 비트 패턴 재해석(주의).
double d=3.2; int i = static_cast<int>(d); // 의도적 내림
const int* pc = &i; int* p = const_cast<int*>(pc); // 위험: 원래가 const였으면 수정 금지


11) 단순 문장과 블록, 스코프

  • 널 문장(;)과 복합문(블록) { ... }. 세미콜론 누락/과다에 주의.
  • 제어문 헤더(예: if, switch, while, for)에서 정의한 변수는 그 문장 내부에서만 유효. 밖에서 쓰려면 바깥에서 정의하라.

12) 조건문 if / switch — 함정 모음

  • 중괄호 잊지 말기: 여러 문장을 함께 실행할 땐 반드시 {}. 들여쓰기는 언어 문법이 아님.
  • dangling else: else는 **가장 가까운 매칭 안 된 if*와 짝을 이룸.
  • switch의 case 라벨은 정수 상수 표현식이어야 하며, 매치된 라벨부터 fall-through로 진행 — 적절히 break 필요.
  • switch 몸체에서 초기화가 있는 변수의 스코프 점프 불가(불법).
switch (c) {
  case 'a':
  case 'A': ++count; break;   // fall-through 의도적
  default: /* ... */
}


13) 반복문 while / 전통적 for / range-for / do-while

  • 전통 for: 초기식 → 조건 → 본문 → 증감 → (조건 재평가 …). 초기식에서 동일 기저 타입의 여러 변수 선언 가능. 일부 항목은 생략 가능.
  • range-for: 시퀀스(begin/end 제공) 를 순회, 선언한 변수 타입은 원소로 변환 가능해야 함.
  • do-while: 본문 먼저 실행 후 조건 검사(조건 비울 수 없음). 조건에 쓰는 변수는 바깥에서 정의해야 함.

14) 점프문: break / continue / goto(비추)

  • break: 가장 가까운 반복문/switch 종료.
  • continue: 가장 가까운 반복문의 이번 반복만 건너뛰고 다음 반복으로.
  • goto: 같은 함수 내 임의 점프로 가독성 저하, 스코프 규칙 위반 위험 — 사용 금지 권고.

15) 예외 처리: throw / try–catch

  • 한 부분에서 처리 불가한 문제를 감지하면, 그 사실을 throw로 알리고, 다른 부분에서 try–catch로 처리. catch 블록이 예외를 실제로 처리한다.
  • 일반적인 형태와 간단 예시가 슬라이드에 제시됨.
try {
  if (bad) throw runtime_error("oops");
} catch (const std::exception& e) {
  cerr << e.what() << '\\n';
}


16) 자주 틀리는 포인트 (체크박스)

  • [ ] =(대입)와 ==(비교) 혼동 금지 — 대입은 우선순위 낮음, 괄호로 명확히.
  • [ ] ++it/it++ 의미 차이와 필요할 때만 후위형 사용.
  • [ ] ptr && *ptr 형태로 단락 평가 활용(널 역참조 방지).
  • [ ] switch에서 break 누락은 fall-through. 의도면 주석, 아니면 break.
  • [ ] sizeof는 피연산자를 평가하지 않음 — 안전한 크기 확인.
  • [ ] 스코프: 제어문 헤더에서 선언한 변수는 그 문장 내부에서만 유효.