사용하지 않는 반환 값을 무효화하는 이유는 무엇입니까?


112
int fn();

void whatever()
{
    (void) fn();
}

사용하지 않은 반품 가치를 무효화 할 이유가 있습니까, 아니면 완전한 시간 낭비라고 생각하는 것이 맞습니까?

후속 조치 :

꽤 포괄적 인 것 같습니다. 자체 문서화 코드가 주석보다 낫기 때문에 사용하지 않는 반환 값을 주석 처리하는 것보다 낫다고 생각합니다. 개인적으로 불필요한 소음 이니까이 경고를 끄겠습니다.

그것 때문에 벌레가 도망 치면 내 말을 먹어 볼게 ...

답변:


79

David의 대답 은이 함수가 반환하는 것을 알고 있지만 명시 적으로 무시하고 있음을 다른 "개발자"에게 명시 적으로 보여 주려는 동기를 거의 다룹니다.

이는 필요한 오류 코드가 항상 처리되도록하는 방법입니다.

C ++의 경우 전체 정적 캐스트 표기법을 사용하는 것이 과도하게 느껴지기 때문에 C 스타일 캐스트도 사용하는 것을 선호하는 유일한 장소라고 생각합니다. 마지막으로 코딩 표준을 검토하거나 작성하는 경우 오버로드 된 연산자 (함수 호출 표기를 사용하지 않음)에 대한 호출도 이것에서 제외되어야한다고 명시 적으로 명시하는 것도 좋습니다.

class A {};
A operator+(A const &, A const &);

int main () {
  A a;
  a + a;                 // Not a problem
  (void)operator+(a,a);  // Using function call notation - so add the cast.

이것은 내가 C 스타일 캐스트를 선호하는 유일한 장소입니다. 내 코딩 표준에서 "a + a;"에 (void)를 추가합니다. 너무 (물론 적절하게 parened, 물론 : p)
Johannes Schaub-litb

8
주제에서 약간 벗어 났지만 왜 "a + a;"를 하시겠습니까? 반환 값을 사용하지 않고 그렇게? 그것은 나에게 부작용의 남용처럼 보이며 코드의 의도를 모호하게 만듭니다.
Rob K

5
글쎄, 당신이 매일 사용할 것은 'a = a'가 될 것입니다. 이것은 객체에 할당 된 값을 반환합니다 (잘 작동하는 모든 클래스에 대해! :)). 또 다른 예는 os << "Hello World"<< std :: endl입니다. 그들 각각은 "os"개체를 반환합니다.
Richard Corden

46

직장에서 우리는 함수가 반환 값을 가지고 있음을 인정하기 위해 그것을 사용하지만 개발자는 그것을 무시해도 안전하다고 주장했습니다. 질문에 C ++ 태그를 지정 했으므로 static_cast 를 사용해야합니다 .

static_cast<void>(fn());

컴파일러가 반환 값을 void로 캐스팅하는 한 의미가 거의 없습니다.


사용되지 않은 반환 값에 대한 경고를 억제합니까?
Paul Tomblin

아니 그렇지 않아. @Mykola : GCC4를 사용하면 경고를 트리거하는 반환 값을 무시해서는 안된다는 속성을 첨부 할 수 있습니다.
David Holm

2
나는 g ++를 사용하는데 그런 캐스트에도 경고를 준다.
klew

2
어떤 경고 옵션을 사용합니까? -Wunused 값은 내 환경에서 경고가 트리거되지 않습니다
Mykola Golubyev

VC ++에서는 경고를 억제합니다
jalf

39

이 작업을 수행하는 진정한 이유는 lint 라는 C 코드에서 사용 된 도구로 거슬러 올라갑니다 .

가능한 문제를 찾고 경고 및 제안을 발행하는 코드를 분석합니다. 함수가 확인되지 않은 값을 반환하면 lint우연한 경우 경고합니다. lint이 경고 를 무음 으로 처리 하려면으로 전화를 (void)겁니다.


2
이 방법으로 시작했을 수 있지만 대부분의 도구에는 이와 같은 경고를 억제하는 다른 메커니즘이 있습니다. 또한-이것이 시작된 이유와 관계없이 특히 안전에 중요한 코드 영역 내에서 이것은 개발자의 의도를 "문서화"하는 일반적인 방법이되었습니다.
Richard Corden

5
GCC는 -Wall을 사용하여 이에 대한 경고를 제공합니다.
greyfade

23

캐스팅 대상 void은 사용되지 않은 변수 및 저장되지 않은 반환 값 또는 식에 대한 컴파일러 경고를 억제하는 데 사용됩니다.

Standard (2003)는 §5.2.9 / 4에서 다음과 같이 말합니다.

모든 표현식은 "cv void"유형으로 명시 적으로 변환 할 수 있습니다. 식 값이 삭제됩니다 .

따라서 다음과 같이 작성할 수 있습니다.

//suppressing unused variable warnings
static_cast<void>(unusedVar);
static_cast<const void>(unusedVar);
static_cast<volatile void>(unusedVar);

//suppressing return value warnings
static_cast<void>(fn());
static_cast<const void>(fn());
static_cast<volatile void>(fn());

//suppressing unsaved expressions
static_cast<void>(a + b * 10);
static_cast<const void>( x &&y || z);
static_cast<volatile void>( m | n + fn());

모든 양식이 유효합니다. 나는 보통 다음과 같이 짧게 만듭니다.

//suppressing  expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);

그것도 괜찮습니다.


1
컴파일러 경고를 항상 끄는 것은 아닙니다. gcc가 void로 캐스팅에 응답하지 않는 것 같습니다
Matt

@Matt : 어떤 버전의 GCC를 사용하고 있습니까? ideone.com 또는 stacked-crooked.com (후자가 더 좋습니다)에 코드를 게시 할 수 있습니까?
Nawaz 2013

1
표준 "버려진"문구는 경고가 린터에 의해 제기되지 않아야 함을 의미합니까?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 : .... 흥미로운 질문입니다. 현재 나는 그것에 대한 답을 모릅니다. 어떻게 든 알게된다면 저와 공유 해주세요.
Nawaz


4

Cast to void는 비용이 들지 않습니다. 컴파일러를위한 정보 일뿐입니다.


1
코드를 작성하는 시간과 이후에 코드를 읽고 이해하는 (그리고 무시하는) 시간이 무료라면 "비용이 들지 않습니다". IMO, 글쓰기는 (void)저에게 시간과 에너지를 소비하고 저자가 표현의 작동 방식을 알고 있는지 궁금해합니다.
wallyk

4

프로그램의 기능을 위해 void로 캐스팅하는 것은 의미가 없습니다. 또한 David의 답변에서 제안한 것처럼 코드를 읽는 사람에게 신호를 보내는 데 사용해서는 안된다고 주장합니다. 당신의 의도에 대해 뭔가를 전달하고 싶다면 코멘트를 사용하는 것이 좋습니다. 이와 같은 캐스트를 추가하면 이상하게 보이고 가능한 이유에 대한 질문이 제기됩니다. 그냥 내 의견 ...


2
이것은 당신이 반환 값에 대해 신경 쓰지 않고 처리하는 것을 잊은 것이 아니라는 것을 다른 사람들에게 명시 적으로 알리는 알려진 패턴입니다.
Spidey

For the functionality of you program casting to void is meaningless자기 설명서 및 컴파일 경고 수, 그것은 정말 아니다. 코드가 스스로 설명 할 때 you should not use it to signal something to the person that is reading the code [...] it is better to use a comment.가장 좋은 주석은 주석 없음 입니다. 그리고 다시 말하지만, 유효한 경고 컴파일러가 프로세스에서 행복하게 유지됩니다.
underscore_d

'이런 캐스트를 추가하면 이상하게 보일뿐 가능한 이유에 대한 의문이 제기됩니다.' 나는 이것들 중 하나를 발견했고 이것이 내가 이것을 읽는 이유입니다. 훈련되지 않은 내 두뇌에 신비한 스택 남용처럼 보였습니다.
mynameisnafe

1

또한 코드가 MISTA (또는 기타) 표준을 준수하는지 확인할 때 LDRA와 같은 자동 도구를 사용하면 반환 된 값을 명시 적으로 (void)로 캐스팅하지 않는 한 반환 유형이있는 함수를 호출 할 수 없습니다.


0

C ++ 17 [[nodiscard]]

C ++ 17은 속성으로 "반환 값 무시 비즈니스"를 표준화했습니다.

따라서 준수 구현이 항상 nodiscard주어진 경우에만 경고하고 그렇지 않으면 경고하지 않기를 바랍니다 .

예:

main.cpp

[[nodiscard]] int f() {
    return 1;
}

int main() {
    f();
}

엮다:

g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -o main.out main.cpp

결과:

main.cpp: In function int main()’:
main.cpp:6:6: warning: ignoring return value of int f()’, declared with attribute nodiscard [-Wunused-result]
    6 |     f();
      |     ~^~
main.cpp:1:19: note: declared here
    1 | [[nodiscard]] int f() {
      | 

다음은 모두 경고를 피합니다.

(void)f();
[[maybe_unused]] int i = f();

통화에서 maybe_unused직접 사용할 수 없었습니다 f().

[[maybe_unused]] f();

제공합니다 :

main.cpp: In function int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
    6 |     [[maybe_unused]] f();
      |     ^~~~~~~~~~~~~~~~

(void)캐스트 작업 표준에 의무적으로 표시되지 않지만 "격려"입니다 : 내가 의도적으로 [[nodiscard] 반환 값을 폐기 할 수 있습니까?

또한 경고 메시지에서 볼 수 있듯이 경고에 대한 한 가지 "해결 방법"은 다음을 추가하는 것입니다 -Wno-unused-result.

g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp

물론 이와 같이 전 세계적으로 경고를 무시하는 것은 권장하지 않습니다.

C ++ 20은 또한 당신이 이유를 추가 할 수 있습니다 nodiscard같이 [[nodiscard("reason")]]:에서 언급 한 바와 같이 https://en.cppreference.com/w/cpp/language/attributes/nodiscard

GCC warn_unused_result속성

의 표준화 [[nodiscard]]이전과 C가 속성을 표준화하기로 결정하기 전에 GCC는 다음과 같은 기능을 구현했습니다 warn_unused_result.

int f() __attribute__ ((warn_unused_result));

int f() {
    return 1;
}

int main() {
    f();
}

다음을 제공합니다.

main.cpp: In function int main()’:
main.cpp:8:6: warning: ignoring return value of int f()’, declared with attribute warn_unused_result [-Wunused-result]
    8 |     f();
      |     ~^~

ANSI C는이에 대한 표준이 없기 때문에, ANSI C는 C 표준 라이브러리 함수는 속성이 없거나 따라서 구현 또는 표시되지해야하는지에 자신의 결정을 한 지정하지 않는 다음에 유의해야한다 warn_unuesd_result,하는 일반적 (void)으로 모든 구현에서 경고를 완전히 피하기 위해 표준 라이브러리 함수에 대한 호출의 반환을 무시 하기 위해 캐스트 를 사용해야하는 이유입니다 .

GCC 9.2.1, Ubuntu 19.10에서 테스트되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.