매크로에서 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_GRENFELZ
1이 아닐 가능성이 높기 때문에? 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
'source' 카테고리의 다른 글
FFT 출력 이해 (0) | 2022.12.18 |
---|---|
Larabel 5 마이그레이션 식별자 이름이 너무 깁니다. (0) | 2022.12.18 |
도커 업데이트 후 Mysql 테이블이 없음: "TableName이 엔진에 없습니다." (0) | 2022.12.18 |
PHP를 사용하여 한 달 중 처음과 마지막 날짜를 찾는 방법은 무엇입니까? (0) | 2022.12.08 |
.prop() vs .attr() (0) | 2022.12.08 |