source

매크로에서 1과 0을 정의하기 위해 3진 연산자를 사용하는 이유는 무엇입니까?

gigabyte 2022. 12. 18. 08:35
반응형

매크로에서 1과 0을 정의하기 위해 3진 연산자를 사용하는 이유는 무엇입니까?

임베디드 프로젝트에 SDK를 사용하고 있습니다.이 소스코드에서 최소한 이상하다고 생각되는 코드를 찾았습니다.SDK의 많은 부분에는 다음과 같은 형식의 소스 코드가 있습니다.

#define ATCI_IS_LOWER( alpha_char )  ( ( (alpha_char >= ATCI_char_a) && (alpha_char <= ATCI_char_z) ) ? 1 : 0 )

#define ATCI_IS_UPPER( alpha_char )  ( ( (alpha_char >= ATCI_CHAR_A) && (alpha_char <= ATCI_CHAR_Z) ) ? 1 : 0 )

여기서 3진 연산자를 사용해도 차이가 있습니까?

아니다

#define FOO (1 > 0)

와 같은

#define BAR ( (1 > 0) ? 1 : 0)

?

평가하려고 했는데

printf("%d", FOO == BAR);

결과 1을 얻으면 같은 값인 것 같습니다.그들이 했던 것처럼 코드를 쓸 이유가 있나요?

맞아요, C에서는 tautologous입니다.당신의 특별한 3차 조건과 (1 > 0)종류int.

단, C++에서는 3항 조건식이 타입이기 때문에 호기심 많은 코너 케이스(예를 들어 오버로드된 함수의 파라미터)에서는 문제가 됩니다.int,반면에.(1 > 0)종류bool.

필자는 C++ 호환성을 유지하기 위해 이 점에 대해 생각해 본 것 같습니다.

비교 결과가 부울이라 산술적으로 직접 사용할 수 없는 보풀 도구도 있습니다.

이름을 대거나 손가락질을 하는 것은 아니지만 PC-lint는 매우 보풀이 많은 도구입니다.

그들이 옳다고 말하는 것은 아니지만, 왜 그렇게 코드가 작성되었는지에 대한 가능한 설명이 될 수 있습니다.

이것은 매우 오래된 코드에서도 종종 볼 수 있습니다.C 표준이 존재하기 이전부터 다음과 같이 기술되어 있었습니다.(x > y)수치 1 또는 0으로 평가합니다.일부 CPU에서는 -1 또는 0으로 평가하는 것이 좋습니다.또한 오래된 컴파일러도 일부 컴파일러는 그대로 따라왔을 가능성이 있기 때문에 일부 프로그래머는 추가적인 방어가 필요하다고 느꼈습니다.

유사한 표현식이 반드시 숫자 1 또는 0으로 평가되는 것은 아니기 때문에 이 경우도 있습니다.예를 들어,

#define GRENFELZ_P(flags) (((flags) & F_DO_GRENFELZ) ? 1 : 0)

내부&-표현은 0 또는 숫자 값 중 하나로 평가됩니다.F_DO_GRENFELZ1이 아닐 가능성이 높기 때문에? 1 : 0규범화하는 역할을 합니다.저는 개인적으로 그걸 이렇게 쓰는 게 더 명확하다고 생각해요.

#define GRENFELZ_P(flags) (((flags) & F_DO_GRENFELZ) != 0)

합리적인 사람들은 동의하지 않을 수 있습니다.여러 가지 표현을 시험해보고, 이런 것들을 줄줄이 가지고 있다면, 누군가 더 쉽게 유지 보수할 수 있다고 판단했을지도 모릅니다.? 1 : 0누가 정말 필요로 하는지 걱정하기보다는 말미에 있는 거죠.

SDK 코드에 버그가 있고, 3진수는 아마 그것을 고치기 위한 진흙이었을 것이다.

매크로가 되는 인수(alpha_char)는 임의의 표현식이 될 수 있으며 'A' & 'c' 등의 표현식은 테스트에 실패하기 때문에 괄호로 묶어야 합니다.

#define IS_LOWER( x ) ( ( (x >= 'a') && (x <= 'z') ) ?  1 : 0 )
std::cout << IS_LOWER('A' && 'c');
**1**
std::cout << IS_LOWER('c' && 'A');
**0**

그렇기 때문에 확장에서는 항상 매크로 인수를 괄호로 묶어야 합니다.

이 예에서는 (파라미터가 있지만) 둘 다 도청되어 있습니다.

#define FOO(x) (x > 0)
#define BAR(x) ((x > 0) ? 1 : 0)

가장 정확하게 대체될 것입니다.

#define BIM(x) ((x) > 0)

@CiaPan 다음 코멘트에서 중요한 점은 파라미터를 여러 번 사용하면 정의할 수 없는 결과가 발생한다는 것입니다.예를 들어.

#define IS_LOWER( x ) (((x) >= 'a') && ((x) <= 'z'))
char ch = 'y';
std::cout << IS_LOWER(ch++);
**1** 
**BUT ch is now '{'**

C에서는 중요하지 않다. C가 있습니다.int 중 하나가 .0 ★★★★★★★★★★★★★★★★★」1

ConditionalExpr ? 1 : 0

효과가 없습니다.

C++로, C++로, C++로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C+로, C++로, C+로, C+로, C+로,int은 타입 C++로 있기 때문에 C++로 되어 있습니다.bool.

#include <stdio.h>
#include <stdbool.h>

#ifndef __cplusplus

#define print_type(X) _Generic(X, int: puts("int"), bool: puts("bool") );

#else
template<class T>
int print_type(T const& x);
template<> int print_type<>(int const& x) { return puts("int"); }
template<> int print_type<>(bool const& x) { return puts("bool"); }


#endif

int main()
{
    print_type(1);
    print_type(1 > 0);
    print_type(1 > 0 ? 1 : 0);

/*c++ output:
  int 
  int 
  int

  cc output:
  int
  bool
  int
*/

}

또한 의도된 효과가 없을 수도 있고, 저자는 단순히 그것이 코드를 더 명확하게 만들었다고 생각했다.

가지 간단한 은 어떤 로 같은 C로 쓰는 이 더 입니다.((a>b)?1:0).

에서는 C-syntax, C-syntax가 .(a>b)?true:false).

또한 이 매크로를 불필요하게 변경할 필요가 없는 이유도 설명됩니다.

어쩌면 임베디드 소프트웨어로서 단서를 줄지도 모른다.ACTI 라인이 반전 로직이 아닌 직접 로직을 사용한다는 것을 쉽게 암시하기 위해 이 스타일을 사용하여 작성된 매크로가 많을 수 있습니다.

언급URL : https://stackoverflow.com/questions/43139144/why-is-the-ternary-operator-used-to-define-1-and-0-in-a-macro

반응형