gcc에서만 범위 전환이 허용됩니다.

gcc에서만 범위 전환이 허용됩니다.

일부 C 코드를 정리하고 데비안 패키지를 빌드하려고 합니다. makefile은 -Wall을 사용하도록 설정되었지만 디빌드는 -Wpedantic을 사용합니다.

코드가 데이터 포인터를 함수 포인터로 변환하기 때문에 이는 "좋은 일"입니다(ISO C에서는 허용되지 않으며 매우 위험합니다... 일부 아키텍처에서는 데이터와 코드가 다른 주소 공간에 있을 수 있음).

그러나 코드는 스위치 문에서도 범위를 사용합니다. 이는 gcc(및 clang) 확장이므로 -Wpedantic에 문제가 있습니다.

case QNAP_PICSTS_SYS_TEMP_0 ... QNAP_PICSTS_SYS_TEMP_70:

(#define은 열거형이 아닙니다)

스위치 범위의 사용은 커널에서 일반적이며 일부 if/else 논리와 함께 기본값을 사용하도록 다시 코딩할 수 있지만 실제로는 더 느립니다(점프 테이블 대 코드).

그러면 1번은 이 기능만 허용하는 옵션이 있고 2번(보너스 포인트용)은 데비안 패키지 규칙에서 어떻게 설정하나요?

옵션은 다음과 같습니다.

http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Warning-Options.html

답변1

나는 광범위한 범위를 사용하여 switch/case/default의 컴파일러 출력을 살펴보았습니다. if/else에서 구현된 동일한 코드와 비교했습니다.소스 코드).

이름과는 별개로, 이는 정확히 동일한 바이너리 코드(Godbolt의 컴파일러 브라우저), debian 12의 기본 GCC 12.2와 함께 사용되는 경우 및 dpkg-buildflagsdebian에서 사용하는 관련 콘텐츠와 함께 사용되는 경우.

다행스럽게도 최신 컴파일러는 간단한 것을 보고 if(state == constant) expr; else if(state == other_constant)…길이가 짧으면 점프 테이블로 변환할 수 있습니다. 따라서 코드는 스위치/케이스와 완전히 동일합니다. 이것은 이미 발생하고 -O1있으므로 위험한 최적화는 아닙니다.

그리고 더욱 놀랍게도 get과 같은 구조는 case 5 ... 74:75와의 비교로 변환됩니다(점프 테이블이 이미 5 미만의 사례를 처리한 후).

따라서 실제로 는 와 보다 더 깔끔해 보인다고 생각하지 않는 한 현대 코드에서 switch를 사용할 이유가 없습니다 . 나는 모른다 - 그리고 나는 당신의 컴파일러도 이것을 하지 않을 것이라고 생각한다: 더 엄격한 범위 지정은 블록을 사용하여 달성된다.casecase CONSTANT: … break;if(state == CONSTANT){ … }

한 가지 예외가 있는데, 이는 물론 case:없이 기본적으로 없이 break시뮬레이션할 수 있다는 것 입니다 .gotogoto

switch(state) {
case 1: 
  value += 0.2f;
case 2:
  retval = 1.0f/value;
  break
// …
}

가설과 동일

if (state == 1) {
  value += 0.2f;
  goto label_in_two;
}
else if(state == 2) 
  label_in_two:
  retval = 1.0f/value;
}

(우리 모두는 의지를 잊어버림으로 인해 발생하는 실수를 알고 있습니다. 그렇지 않은 경우 break;의지를 사용하면 동일한 문제가 발생합니다.goto매우주의 깊은. )

이것은 실제로 유한 상태 기계를 구축하는 사람들을 위한 편리한 구성이며 범위와 함께 사용하기 위한 것이 아니라는 점을 이해하시기 바랍니다. switch오래되지 않은 컴파일러에 비해 전혀 이점이 없으며 if/else if명확한 제어가 없는 경우 스트림에는 수많은 오류 소스가 있습니다.

그래서 저는 돌이켜보면 현대 컴파일러 최적화에 대한 지식을 바탕으로 GNU의 case범위 기능이 잘못 고려되었다고 생각합니다. 따라서 경고는 합리적이었습니다.

그래서 저는 이 경고를 제거하는 올바른 방법은 switch//를 // 구문으로 변환하는 것이라는 결론에 도달했습니다.casedefaultifelse ifelse

관련 정보