kernel.h의 min 매크로에서“(void) (& _min1 == & _min2)”의 기능은 무엇입니까?
에서는 kernel.h는 분으로 정의된다 :
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
나는 그 선 (void) (&_min1 == &_min2);
이 무엇을하는지 이해 하지 못한다. 일종의 유형 검사입니까?
진술
(void) (&_min1 == &_min2);
보장 된 "no-op"입니다. 그래서 그것이 존재하는 유일한 이유는 부작용 때문입니다.
그러나이 진술에는 부작용이 없습니다!
그러나 유형 x
과 y
호환되지 않는 경우 컴파일러가 진단을 실행하도록합니다 .
로 테스트 _min1 == _min2
하면 값 중 하나를 다른 유형으로 암시 적으로 변환합니다.
그래서 그것이하는 일이라고 생각합니다. 컴파일 타임에 x
및 의 유형 y
이 호환되는지 확인 합니다.
include / linux / kernel.h 의 코드는 이것을 "불필요한"포인터 비교라고합니다. 이것은 실제로 x
와 의 유형이 y
동일한 지 확인하는 엄격한 유형 검사 입니다.
여기서 유형이 일치하지 않으면 컴파일 오류 또는 경고가 발생합니다.
이것은 유형 검사를 제공하고 포인터 간의 동등성은 호환 가능한 유형 사이에 있어야하며 gcc
그렇지 않은 경우 경고를 제공합니다.
포인터 간의 동등성을 위해서는 포인터가 C99 표준 섹션 Equality 연산자 초안 에서 호환 가능한 유형 이어야한다는 것을 알 수 있습니다 .6.5.9
다음 중 하나가 유지됩니다.
다음을 포함합니다.
두 피연산자 모두 호환 유형의 규정 된 또는 규정되지 않은 버전에 대한 포인터입니다.
호환 가능한 유형 및 다음과 같은 복합 유형 섹션에서 호환 가능한 유형 이 무엇인지 찾을 수 있습니다 .6.2.7
유형이 동일한 경우 두 유형은 호환 가능한 유형을 갖습니다.
osnews에 대한이 토론 에서는이 내용 도 다루며 동일한 코드 샘플을 포함 하는 Linux 커널 문서 의 GCC 해킹에서 영감을 받았습니다 . 대답은 다음과 같습니다.
typechecking과 관련이 있습니다.
간단한 프로그램 만들기 :
int x = 10; long y = 20; long r = min(x, y);
다음 경고를 제공합니다. 경고 : 구별 포인터 유형 비교에 캐스트가 없습니다.
다음 을 설명하는 http://www.osnews.com/comments/20566 을 참조 하십시오 .
유형 검사와 관련이 있습니다.
간단한 프로그램 만들기 :
int x = 10; long y = 20; long r = min(x, y);
다음 경고를 제공합니다. 경고 : 구별 포인터 유형 비교에 캐스트가 없습니다.
"유형 검사와 관련이 있습니다. 간단한 프로그램 만들기 :
int x = 10;
long y = 20;
long r = min(x, y);
다음 경고를 제공합니다. 경고 : 구별 포인터 유형 비교에 캐스트가 없습니다. "
리눅스 커널은 이와 같은 것들로 가득 차 있습니다 ( "타입 안전성"및 기타 유사한 고려 사항을위한 무상 gcc 전용 해킹). 저는 이것이 매우 나쁜 관행이라고 생각하고 누군가가 요구하지 않는 한 따르지 말 것을 촉구합니다.
PMG는 바로 해킹의 목적에 대해이지만, 어떤 제정신 사람이 정의하는 것 min
등 ((x)<(y)?(x):(y))
.
커널 정의는 한 인수가 int
이고 다른 인수가 인 경우 와 같이 많은 올바른 사용을 배제합니다 long
. 나는 그들이 정말로 배제하기를 원했던 것이 서명 불일치라고 생각합니다. 예를 들어 min(-1,1U)
1입니다. 이것을 주장하는 더 좋은 방법은 .NET에 대한 컴파일 타임 주장을 사용하는 것입니다 ((1?-1:(x))<0)==((1?-1:(y))<0)
. 여기에는 gcc 관련 해킹이 필요하지 않습니다.
'IT TIP' 카테고리의 다른 글
.NET 4.0에 기본 제공 이진 검색 트리가 있습니까? (0) | 2020.12.04 |
---|---|
ggplot ()으로 선 색상 변경 (0) | 2020.12.04 |
require_self는 무엇을 의미합니까? (0) | 2020.12.04 |
이 작업을 수행 할 수없는 이유 : dynamic x = new ExpandoObject {Foo = 12, Bar = "twelve"} (0) | 2020.12.04 |
HTML 닫기 (0) | 2020.12.04 |