[42seoul] 4 circle - CPP Module 06

하이초·2023년 1월 12일
0

42seoul

목록 보기
7/11
post-thumbnail

CPP06 github 😋

C++ 타입 캐스팅

👀 cpp 06은 타입 캐스팅에 대해 알아보는 과제였다. 그래서 본격적인 과제 얘기를 하기 전에 c++에서 사용하는 캐스팅 연산자를 얘기해보기로 한다!

1. static_cast(정적 캐스트): static_cast<new_type>(expression)

  • 형 변환에 대한 타입체크를 런타임이 아닌 컴파일시에 정적으로 수행한다.
  • 따라서 맞지 않는 형 변환 (ex. int <-> char*)으로 코드를 작성할 시 컴파일 단계에서 에러가 발생하여 올바른 형변환을 할 수 있게 해준다.
  • 요 형변환은 cpp00 ex00에서도 한 번 살펴본 바 있다.
  • static_cast는 const를 제거할 수 없다.

2. const_cast: const_cast<new_type>(expression)

  • 말그대로 const를 제거하는 데 사용하는 캐스트 연산자이다.
  • 그러나 const 속성을 영구적으로 제거하는 것은 아니고 일시적으로 값변환을 가능하게 한다.

3. reinterpret_cast: reinterpret_cast<new_type>(expression)

  • 포인터 간의 형 변환을 가능하게 해주는 캐스트 연산자.
  • 또 정수 <-> 포인터간 형 변환도 가능하다. 이때 정수값이 포인터의 절대 주소로 들어가게 된다.
  • 🚨 주의해야할 점은 int* -> char -> int* 와 같은 순서로 캐스팅 할 경우 원본 값을 잃을 수 있다. char형의 경우 1byte이기 때문에 포인터 주소값을 전부 담을 수 없기 때문이다.
  • 다시 말해 이 캐스트 연산자의 경우 expression에 해당하는 것을 new_type으로 비트 단위로 바꾸는 것이기 때문에 주의하여 사용해야 한다.
  • 패킷통신할 때 사용한다고 하는데.. 잘 모르겠다.

4. dynamic_cast(동적 캐스트): dynamic_cast<new_type>(expression)

  • 상속에 활용되는 캐스트 연산자.
  • 부모 포인터를 자식 포인터로 다운 캐스팅하여 사용할 수 있다. 조건문에 활용하여 해당 자식포인터가 해야할 일에 보내줄 수 있다.
  • 이름부터 알 수 있듯이 static_cast와는 반대로 런타임시에 에러가 검출된다. (다형성을 띄지 않은 객체간 변환에 사용 시 컴파일 에러가 발생함. v-table을 확인하기 때문이라고 한다.)
  • 실패 시 포인터형은 NULL 포인터를, 참조형은 예외(bad_cast)를 던져 오류를 확인할 수 있다.
  • 업캐스팅 시에도 가능하다고..한다..?

1. ex00

👀 ex00은 정말 손이 너무너무 많이 가던 과제. 아주 구찮아 죽겠어 정말! 입력값에 대하여 char, int, float, double로 변환하여 출력해야 하는 과제. 예외처리로 신경써야할 것이 많아 너무 피곤했다 흑흑.

🥨 공통

  • 공통적으로는 strtod함수를 활용하여 인풋값을 double로 변환하고 그 값의 끝이 '\0'(double)이나 'f'(float)가 아닌 경우 impossible 에러 처리를 위해 플래그를 켜주었다.

🥨 strtod: double strtod(const char *nptr, char **endptr)

  • 변환할 문자열과 endptr을 넣으면 문자열을 실수로 변환한 값을 보내주며 endptr을 실수 다음 위치를 가리키게 변경해준다.
  • 따라서 endptr의 값을 확인하였을 때 input 문자열이 42나 42.3과 같은 실수일 경우 모두 변환을 마친 상태이니 문자열의 끝인 '\0'이거나, 42.3f와 같은 실수일 경우 f가 끝값인 경우 2가지 외에는 숫자가 아닌 다른 문자들이 들어있다는 뜻이다.
  • 다만 'c'와 같이 char형 문자가 하나 들어왔을 경우는 또 얘기가 달라 이는 예외적으로 처리해주었다.
  • 과제에서 string으로 받으라고 되어있기 때문에 nptr 형식을 맞춰주기 위해 c_str()함수를 사용하였다.

🥨 char

  • 앞서 말한 'c'와 같은 경우 예외처리를 위해 input의 길이가 1이고, isprint함수를 통해 출력이 가능한 것이 확인 되면 해당 문자를 캐스팅하여 출력하도록 했다.
  • 그 외 플래그에 따라 impossible 혹은 isprint가 아닌 것들에 대해서는 non displayable 예외를 터뜨렸다.
  • 나머지 정상적인 것들은 변환된 value값에 해당하는 것들 = 아스키 코드내에서 출력이 가능한 문자들이 출력되도록 했다.

🥨 int

  • 역시 'c'와 같은 경우 예외처리를 진행했다. 다만 char 조건에 더하여 아스키 코드내에서 숫자가 아닌 부분에 대해서만 인풋값을 그대로 활용하였다. '9'가 들어온 경우에 9가 출력되어야 하는데 아스키 코드 9에 해당하는 문자가 출력되면 안되기 때문이다.
  • 나머지는 char와 동일.
  • 오버플로우와 언더플로우 처리는 전혀 하지 않았다.

🥨 float

  • 얘는 int에 더해 2가지 예외를 더 봐주었다.
  • 과제에서 요구하는 inf와 nan처리! 부호를 위해 std::showpos를 사용하였다. 기본 옵션은 std::noshowpos이기 때문에 부호를 확인하려고 하는 경우 해당 옵션을 활성화시켜줘야 한다.
  • ㅇㅣ오ㅏ 관련하여 std::isnanstd::isinf와 관련된 얘기가 아주 많길래 그냥 속편히 하려고 다른 방법을 시도했다. 참고한 문서는 팔만코딩경! 정리가 잘 되어있다!
  • 또 '42'는 '42.0f'로, '42.3'은 '42.3f'로 나와야 하기 때문에 floor 함수를 활용하여 기존 값과 플로어 함수를 사용한 값이 다를 경우 소수가 존재하는 것이기 때문에 f만 붙여주고 소수가 존재하지 않는 경우에 대해서만 .0f가 붙을 수 있도록 해주었다.

🥨 double

  • float와 완죠니죠니 동일!

2. ex01

👀 ex01은 reinterpret_cast<new_type>(expression) 타입 캐스트를 사용해보는 과제였다.

🥨 reinterpret_cast

  • 자세한 설명은 상단을 참고.
  • 애초에 c++스타일 타입캐스트라는 것이 c의 (int)처럼 맞지 않는 형변환을 진행하게 두지 않고 컴파일 단계에서 막아준다는 것인데... 뭐 어쨌든 필요가 있었으니 만들어둔거겠지?

3. ex02

👀 ex02는 dynamic_cast<new_type>(expresiion) 타입 캐스트를 사용해보는 과제였다.

🥨 dynamic_cast

  • 실패 경우에 대해 조금 더 자세하게 풀어 써보자면~!
    • 1) new_type = pointer -> null pointer (과제의 void identify(Base *p)에 해당)
    • 2) new_tyep = reference -> bad_cast (cpp05에서 살펴봤던 예외 중 하나인 bad_cast 에러로 exception이 발생한다. 과제의 void identify(Base &p)에 해당)
  • 따라서 포인터로 체크할 경우 =NULL로, 참조자로 체크할 경우 try-catch문으로 맞지 않는 형을 확인할 수 있다.

🚴 CPP 가보자고!

profile
개발국대가 되는 그 날까지. 지금은 개발 응애.

0개의 댓글