인프런 커뮤니티 질문&답변

durams님의 프로필 이미지
durams

작성한 질문수

홍정모의 따라하며 배우는 C++

4.5 형변환 Type conversion

캐스팅에 대해 질문이 있습니다.

해결된 질문

작성

·

251

·

수정됨

1

18:30 즈음부터 명시적 형변환에 대한 설명이 나옵니다. 내용은 아래와 같습니다.

// C 스타일 캐스팅
(int)4.0;

// CPP 스타일 캐스팅
int(4.0);

그런데 따로 알아보니 강의 내용과 좀 맞지 않는 부분이 있는 것 같았습니다.

 

아래 링크를 간략하게 설명하면,

https://en.cppreference.com/w/cpp/language/explicit_cast

(int)4.0 과 같은 C-style cast를 컴파일러가 만나게 되면 아래 순서에서 맨 처음으로 해당 캐스팅의 조건을 만족하는 것이 선택되어 수행된다고 합니다. (컴파일 될 수 없더라도!)

  1. const_cast

  2. static_cast

  3. static_cast 다음 const_cast

  4. reinterpret_cast

  5. reinterpret_cast 다음 const_cast

즉, C-style cast를 사용하면 위 캐스팅 종류 중 어떤 것이 사용되었는지 명확히 알 수 없다는 것을 의미합니다.

여기에 추가적으로, 클래스 간 상속관계에서 privateprotectedpublic으로 간주될 수도 있는 등의 예외도 존재하기 때문에 최근에는 C-style cast가 권장되지 않는 것으로 보입니다. 19:10에는 C-style cast와 나머지 캐스팅 방식 간에 기능성 차이가 없다고 나오는데, 차이가 충분히 있는 것 같습니다. 아래 Stackoverflow 글에도 관련 내용이 있습니다.

https://stackoverflow.com/questions/27359961/c-difference-between-reinterpret-cast-and-c-style-cast

 

그리고 위에 있던 cppreference 링크의 functional-style cast 부분을 살펴보면, CPP 스타일 캐스팅이라고 소개된 int(4.0)는 사실상 C-style인 것을 알 수 있습니다.

If there is exactly one expression in parentheses, this cast expression is exactly equivalent to the corresponding C-style cast expression.

그래서 const_cast, static_cast, reinterpret_cast가 CPP 스타일 캐스팅이라고 소개되는 것이 옳지 않나 생각합니다.

 

답변 2

2

홍정모님의 프로필 이미지
홍정모
지식공유자

안녕하세요?

 

  1.  

    여기서 C++ 스타일이라고 얘기한 것은 C언어 공부한 학생들에게 C++에서는 문법에 차이가 있다는 의미입니다.

간단히 얘기하면 C에서는 int a = int(3.4);이 컴파일이 안됩니다.

어떤 종류의 캐스팅인지 더 구체적으로 적어놓으면 당연히 좋겠죠. 더 구체적으로 적을 수 있으니 구체적으로 적는 것이 C++ 스타일이라고 말하는 것도 말이 됩니다. 그렇다면 C++에서 int a = int(3.4);를 사용하는 것이 C스타일인가? 정작 C에서는 컴파일이 안되는데? 그리고 C++에서 컴파일이 되는거면 다 C++ 스타일이라고 봐야 하는거 아닌가? 이런 얘기도 나올 수 있을 정도로 복잡한 상황입니다.

그러나 원론적으로는 생각하시는 대로 C++에서는 어떤 종류의 형변환인지를 더 구체적으로 지정해줄 수 있으니까 적어주면 좋은 것은 맞습니다. 실무 코드나 유명한 오픈소스에서도 항상 static_cast를 쓰는 것은 아닙니다. 이런 현상이 C언어 사용자로부터 오는 관성 때문인지 아니면 C++에서도 'C-style' cast를 써도 된다고 보는 것인지 까지는 모르겠습니다. 하지만 만약에 C++ 커뮤니티에다가 꼭 어떻게 해야만 한다라고 압박하는 얘기가 나오면 대부분의 경우 논란이 꽤 있을겁니다.

아래 링크가 원 교재 링크입니다. 원 교재에는 C++ 스타일이라는 표현이 사라졌는데 제가 강의를 만들면서 오류가 생긴 것인지 아니면 그사이에 원 교재가 수정되었는지는 잘 모르겠네요.

https://www.learncpp.com/cpp-tutorial/explicit-type-conversion-casting-and-static-cast/

 

2.

static_cast와 나머지 방식이 차이가 없다고 얘기한 것이 아니라 int(4.0)과 static_cast<int>(4.0)의 결과에 차이가 없다는 얘기였습니다. 제가 들어도 표현이 애매한 면이 있긴 합니다.

 

  1.  

    링크 글에서 정확히 어느 부분을 얘기하시는 것인지는 모르겠는데 일단 제가 추측해보건데 중간에

static_cast - Effectively this converts an object from one type to another. Note this can change the value (static_cast<float>(1) doesn't have the same bit pattern as 1 for instance).

의 얘기는 static_cast<float>(1) -> float 1.0f 과 정수 1이 비트 배열이 다르다는 얘기입니다.

 

4.

Stroustrup글에서 What good is static_cast? 부분만 읽어보았는데, 잘 보시면 새로운 스타일이 추가가 되었다는 표현이 있고 새로 추가된 것이 C++ 스타일이라는 표현은 없습니다. 일반적으로 좋은 C++ 프로그래밍 스타일은 형변환을 할 때 프로그래머의 의도가 무엇인지를 컴파일러에게 떠넘기지 않고 코드에 잘 적어놓는 것이겠죠. 유교경전 문구 가지고 옥신각신 싸우는 것은 의미가 없다고 생각합니다만, C++ 스타일이 뭐냐라고 딱 정리하기는 여전히 쉽지 않은 것으로 알고 있습니다. (보통 우리 회사는 이렇게 한다 정도로 합의)

 

4.If there is exactly one expression in parentheses, this cast expression is exactly equivalent to the corresponding C-style cast expression. <- 이 문장만 보면 equivalent는 동등하다이지 같다는 것은 아닙니다.

 

혹시 도움될까 해서 덧붙이자면, 미국 애들끼리는 대화하면서 이런거 꼬치꼬치 따지고 고쳐주고 하는 경우가 많습니다. 가상의 예시) "I think A is B", "No, A is equivalent to B" 이런 대화가 많습니다.

 

이렇게 꼼꼼히 따져가면서 공부하시는 것은 개인에게는 당연히 좋은 일입니다만, 이 강의의 목표는 문법 자체를 꼼꼼히 익히는 것이 아니라는 점을 어느정도 감안을 하고 보셔야할 것 같습니다. 강의에 부족한 점이나 오류가 없다는 얘기는 아닙니다. 제가 언어 전공자가 아니라는 점도 한계가 있는 것 같고 개인적인 지향성도 응용 분야 쪽이라는 점도 영향이 있을 것 같습니다. 참고로 프로그래밍 언어 자체를 전공하신 분들도 계시니까 엄밀한 공부를 원하신다면 그런 분들의 강의나 교재를 보시는 방법도 있을 것 같습니다. 원 교재 같은 경우 예전에는 레딧에서 learncpp 보고 공부한 사람 걸러라 라는 얘기도 있었는데 최근에는 오랜 기간 동안 엄격한 검증을 거쳤기 때문에 많이 개선되었을 것으로 생각됩니다.

 

  • 두 분이 좀 더 옥신각신 하시는 것도 좋은 의사소통 연습이 될거라고 봅니다. 저는 제가 항상 옳은 것은 아니라는 얘기를 하려다가 좀 길어졌네요.

durams님의 프로필 이미지
durams
질문자

안녕하세요 선생님. 답변해주신 내용 잘 읽었습니다.

Github 쪽을 검색해보니, 작업 시 C-style을 사용하지 말고 C++ style을 사용해라고 권고하는 Issue들이 적지 않게 있더라구요. C++ style이 명확하고 안정성이 좋은건 사실이지만, C-style을 그대로 편하게 사용하는 사람들이 많은 것도 사실인 것 같습니다. Stackoverflow에는 'Don't use them, ever.' 이라거나 'never use'라고 좀 강경하게 C-style을 반대하는 사람도 있더라구요.

개인적으로는 이런 보다 좋은 품질의 프로그램 작성을 다 같이 권장하는 분위기가 나쁘지는 않은 것 같습니다. 사실 제가 아직 실무에 있어본 적이 없어서 프로그램 작성 시 어떠한 무조건적인 규칙을 따르는 것이 일터에 주는 영향 같은 것은 생각을 잘 못하겠지만, C-style이라는 오래 사용되던 방식을 갑자기 모든 사람이 사용하지 못하게 하는 것도 말이 안되긴 하네요.

제가 너무 강의에서 벗어난 부분에 대해 시시비비를 가리려는 느낌이 좀 없지않아 있었던 것 같네요. 실제 사용을 잘하는 것이 더 의미있는 거겠죠.

그와 별개로 저는 이런식으로 생각해보고 질문글 달고 하는게 재밌더라구요. 배우는 입장에서 여러 자료를 찾아보니 공부도 많이 되구요. 말씀 감사합니다.

홍정모님의 프로필 이미지
홍정모
지식공유자

코딩 스타일이야 말로 자동화가 가능합니다. 대기업은 내부적으로 커밋하려고 하면 자동으로 고쳐주는 시스템이 있습니다. 아예 그런 기능만 담당하는 팀도 있습니다. 'Don't use them'이라고 사람이 조언해주는 것이 아니라 누군가가 하면 안되는 일을할 때 그걸 자동으로 경고해주거나 수정해주는 시스템을 만드는 것입니다. 간단하게는 포매터 생각하시면 됩니다. 극단적인 사례를 들면, 코딩하면서 줄바꿈을 잘 하면 코드 품질을 높이는 데에 도움이 되던 시대도 있었습니다. (비용 산정에 줄 수 반영) 이걸 매번 하지마라 주의해라 경고를 했어야 하는 시대에 일하던 분들에게는 프로그래밍 교육이라고 하면 변수명 잘 짓고 줄바꿈 잘하는 거였습니다. 지금은 합의된 규칙에 따라 포매터를 설정해놓고 파일 저장하면 자동으로 정리를 해줍니다. 참고로 저는 스택오버플로우를 볼 때 언제 쓰여진 글인지 날짜도 꼭 확인합니다.

제가 학생들에게 계속 강조하는 것은 새로운 비즈니스 모델을 찾아내는 것이 중요하다는 것입니다. 예를 들면 인스타그램이 나올 때 비슷한 비즈니스 모델을 시도하는 벤쳐들이 여러개 있었는데 결국 하나만 남았습니다. 어떤 아이디어가 시장에 나오면 초기에는 여러 회사들이 경쟁하다가 하나만 남습니다. 그러면 나머지는 합병되어서 같이 가든가 아니면 다른 아이디어를 시도하러 갑니다. 최근에 틱톡도 비슷한 과정을 거쳐서 자리를 잡았습니다. 학습능력이 좋은 학생들일수록 창업자 마인드로 접근을 하셨으면 좋겠습니다.

durams님의 프로필 이미지
durams
질문자

그렇군요... 감사합니다 선생님. 넓게넓게 보겠습니다 ㅎㅎ

2

안녕하세요? 질문&답변 도우미 Soobak 입니다.

 

좋은 궁금증이시네요.

하지만, 강의에서 int(4.0) 과 같은 형변환을 C++ 스타일의 캐스팅이라고 말씀해주신 교수님의 설명이 정확합니다.

 

함수형 스타일 캐스팅(Functional-style cast) 에서 중요한 부분은 C++ 의 문법적인 특성을 반영한다는 점입니다.
함수형 캐스팅은 C++ 에서 함수 호출 구문과 일관성을 가지며, 이는 C++ 의 자료형 및 함수 오버로딩 기능을 고려하여 설계된 것입니다.

정확한 C++ 표준에 따르면 T(expression) 의 형태로 정의되며, 여기서 T 는 자료형, expression 은 변환하고자 하는 값을 의미합니다.

이는 C++ 의 캐스팅 연산자들 (말씀해주신 static_cast , const_cast , reinterpret_cast 외에도 dynamic_cast 가 있으며, 강의 12.10 동적 형변환 을 비롯하여 이어지는 강의 전반에 걸쳐서 자세히 학습하시게 됩니다.) 과 별도로, 보다 함수 호출에 가까운 문법적 형태를 가지고 있습니다.

 

즉, 함수형 캐스팅이 내부 기능적으로는 C 스타일 캐스팅과 동일하게 작동한다고 하더라도, 문법적으로 C++ 의 특성을 반영하고 있습니다.

 

이에 대해서는 추후 강의 9.8 형변환을 오버로딩 하기1:30 부분 경 operator int() 를 오버로딩하는 부분의 교수님 설명을 참고해보시면 아주 잘 이해가 되실 것 같습니다.

 

또한, 첨부해주신 cppreference 링크에서 함수형 스타일 캐스팅의 내부 작동 방식이 C-style 캐스팅 방식과 동일하게 작동한다는 것을 굳이 비교하며 추가적인 설명을 한 것 또한, 함수형 스타일 캐스팅이 C-style 캐스팅 방식이 아니기 때문에 그 작동 방식에 대해서 비교하며 설명한 것으로 이해하시면 좋을 것 같습니다.

 

요약드리자면, cppreference 링크에서 함수형 캐스팅과 C스타일 캐스팅에 대해서 명시한 부분은 '내부 기능 동작에서의 동일한 부분' 에 관한 것입니다.
하지만, 함수형 캐스팅 방식은 C++ 의 문법적인 특성을 반영한 C++스타일의 캐스팅 방식입니다.

durams님의 프로필 이미지
durams
질문자

답변 감사합니다. 본 질문글은 제가 강의를 완강하고 다시 노트를 정리하며 복습하는 과정에서 생긴 의문을 여쭤본 것이라 언급해주신 내용에 대해 알고 있습니다.

functional-style cast는 문법적으로 함수 호출에 가까운 형태를 지니며, 실제로 형변환 연산자를 오버로딩하여 사용하는 것이 가능하다는 점에서 객체지향이라는 C++의 성격을 활용하기에 C++ 스타일이라고 말할 수 있다고 말해 주셨습니다. 내용이 이해도 잘 되었습니다.

그런데 제 생각에는 functional-style은 일반적으로 권장되는 방법들인 static_cast를 포함한 다른 C++ 스타일 캐스팅과는 그 의미가 다른 것 같습니다. static_cast, const_cast 등은 변환의 의도를 명확히 표시하여 알 수 있게끔 하며 안정성도 높은 것이 특징인데 function-style cast는 내부적으로 그 중 하나를 수행할 뿐 그 자체를 C++ 스타일로 보기에는 어렵다고 생각합니다.

그래서 '무엇을 C++ 스타일 캐스팅으로 보아야 하나?'가 관건이긴 합니다.

Bjarne Stroustrup이 아래와 같이 말한 내용이 있습니다.

The "new-style casts" were introduced to give programmers a chance to state their intentions more clearly and for the compiler to catch more errors.

https://www.stroustrup.com/bs_faq2.html#static-cast

C++ 스타일 캐스팅이란 캐스팅의 목적을 명확히 표시하고 컴파일러가 에러를 더욱 잘 잡아내도록 하는 것이 목적이라고 되어 있습니다. 이외의 검색결과에서도 functional-style cast는 C-style과 동일하게 동작하는 것이며, C++ style cast 네 가지를 목적에 맞게 사용하는 것을 권장하고 있습니다.

 

또한, 첨부해주신 cppreference 링크에서 함수형 스타일 캐스팅의 내부 작동 방식이 C-style 캐스팅 방식과 동일하게 작동한다는 것을 굳이 비교하며 추가적인 설명을 한 것 또한, 함수형 스타일 캐스팅이 C-style 캐스팅 방식이 아니기 때문에 그 작동 방식에 대해서 비교하며 설명한 것으로 이해하시면 좋을 것 같습니다.

위 부분은 어떤 의미인지 잘 이해가 되지 않습니다. 강의에서 설명되는 사례인 int(4.0) 같은 경우의 functional-style cast는 C-style cast가 완전히 동일합니다.

안녕하세요? 질문&답변 도우미 Soobak 입니다.

 

말씀해주신 내용 잘 이해되었습니다.

교수님께서 답변해주신 내용 또한 확인한 후, 좀 더 넓은 생각으로 토론을 이어나가는 것도 저에게 좋은 경험이 될 것 같아 즐거운 마음으로 답변을 이어 드립니다.

 

마지막, 제가 질문자님을 납득시켜드리지 못한 내용에 대하여 좀 더 풀어 설명드리면 다음과 같습니다.

  • c++ 에는 4가지의 형변환 연산자가 존재

    • static_cast, const_cast, reinterpret_cast, dynamic_cast

 

  • 이 때, 형변환 방식에 대하여 비교 기준을 '명시의 유무' 로 삼아 구분해본다면, '명시적 형변환' 과 '암시적 형변환' 두 가지로 나눌 수 있을 것

 

  • 이 때, '명시적 형변환' 에 대해서 비교 기준을 '언어적 특성' 으로 삼아 구분해본다면, 'C언어 스타일 형변환' 과 'C++언어 스타일 형변환' 으로 나눌 수 있을 것

    • (int)4.0 과 같은 방법은 C언어에서의 형변환과 문법적인 형태가 동일하기 때문에 'C언어 스타일'

    • static_cast<int>(4.0) 과 같은 방법은 C++언어에서의 문법적인 형태이기 때문에 'C++언어 스타일'

    • int(4.0) 과 같은 방법은 C++ 언어에서의 문법적인 형태이기 때문에 'C++언어 스타일' (C언어에서는 위와 같은 문법으로 형변환을 진행할 수 없음)

 

  • 위 3가지의 명시적 형변환 방식에 대하여, '내부 작동 방식' 을 기준으로 삼아 범위를 나눠본다면 (int)4.0int(4.0) 은 내부적인 형변환 연산자 선택에 있어서 작동방식이 동등함.(개인적으로는 그냥 '같다' 라고 표현하고 싶습니다.), 반면 static_cast<int>(4.0) 과 같이 연산자까지 명시하는 명시적 형변환은 이와 구분됨.

 

  • 이 때, cppreference 의 글은 함수형 스타일의 형변환 방식을 C언어 스타일의 형변환 방식과 '작동 기능' 측면에서 비교하여 언급하고 있음.

    • 어떠한 대상 둘을 '비교' 한다는 것은, 그 둘을 구분하는 '기준' 이 있다는 것이므로,
      '굳이' 함수형 스타일 형변환 방식을 C언어 스타일 형변환 방식과 비교하고 있다는 것은 그 둘이 다르기 때문이라고 생각.

 

  • 여기서 제 생각은, 함수형 스타일 형변환 방식은 '문법적으로' C++언어 스타일 이기 때문에, C언어 스타일 형변환 방식과 구분되는 것이며, 다만 이 둘을 '내부 작동 방식' 을 기준으로 살펴보았을 때 함수형 스타일 형변환 방식의 작동 방식은 C언어 스타일 형변환 방식의 작동 방식과 동등하다는 것 입니다.

durams님의 프로필 이미지
durams
질문자

작성하신 답변 잘 읽었습니다. 저도 마지막에 결론 내리신 것과 같은 생각입니다. 사실 이 주제는 그렇게 중요한 것이 아닐지도 모르겠네요.

강의 내용과는 크게 상관이 없는 내용이지만, 복습을 이어서 하다 열거형 부분에서 왜 enum classstruct 그리고 class는 전방 선언이 되지만 enum은 되지 않는지 궁금해서 검색했는데 명확한 답을 못 찾겠더라구요. 그런데 스택오버플로우의 한 댓글이 아래와 같이 달려 있더라구요.

It was not allowed in C++ back then because it is not allowed in C. It is not allowed in C because there was no pressing need for such things back in 1980. It is not allowed in C++ now because no one cares. People should not be using old-style enums in new development anyway, why revise rules that govern them?

사실 이것은 C 언어의 제약이 초기 C++에 준 영향이 그대로 이어진 것일지도 모르며, 더군다나 새로운 개발에서는 기존의 열거형이 필요한 경우 enum 대신 enum class를 사용할 것이 권장되므로, 이러한 논쟁에 대해 생각할 이유가 없을지도 모른다... 라는 내용이었습니다.

비슷한 관점에서 생각했을 때, C-style과 C++ style의 정확한 정의에 대해 생각하는 것이 크게 의미있는 활동은 아닌 것 같다는 생각이 뒤늦게 드네요. 물론 여러 자료를 찾아보는 과정에서 여러 형 변환 방법이 생겨난 이유와 그 목적에 대해서 명확히 알게 되었다는 점에서 그 시간 자체는 의미있었던 것 같습니다. 적극적으로 의견교환 해주셔서 감사합니다.

durams님의 프로필 이미지
durams

작성한 질문수

질문하기