스위치 케이스의 구문은 유효하지만 가치가 없는 구문인가?
약간의 오타를 통해 나는 우연히 이 구조를 발견했다.
int main(void) {
char foo = 'c';
switch(foo)
{
printf("Cant Touch This\n"); // This line is Unreachable
case 'a': printf("A\n"); break;
case 'b': printf("B\n"); break;
case 'c': printf("C\n"); break;
case 'd': printf("D\n"); break;
}
return 0;
}
...인 것 같다.printf
맨 위에switch
진술은 유효하지만, 또한 완전히 도달할 수 없다.
접근할 수 없는 코드에 대한 경고도 없이 깔끔하게 컴파일을 받았는데, 이건 무의미해 보여
컴파일러가 연결할 수 없는 코드로 플래그를 표시해야 하는가?
이게 무슨 소용이야?
아마도 가장 유용한 것은 아니지만, 완전히 쓸모없는 것은 아닐 것이다.다음에서 사용할 수 있는 로컬 변수를 선언하는 데 사용할 수 있음switch
범위
switch (foo)
{
int i;
case 0:
i = 0;
//....
case 1:
i = 1;
//....
}
표준 ()N1579 6.8.4.2/7
)에는 다음과 같은 샘플이 있다.
예: 인공 프로그램 조각 내
switch (expr) { int i = 4; f(i); case 0: i = 17; /* falls through into default code */ default: printf("%d\n", i); }
식별자가 있는 개체
i
(블록 내에) 자동 저장 지속 시간이 있지만 초기화되지 않으며, 따라서 제어 식이 0이 아닌 값을 갖는 경우 에 대한 호출printf
함수는 불확실한 값에 접근할 것이다.마찬가지로, 함수에 대한 호출f
손이 닿지 않다
P.S. BTW, 샘플은 유효한 C++ 코드가 아니다.그런 경우에는 ()N4140 6.7/3
, 강조 표시 내 항목:
지 않는 한 변수가 사소한 기본 생성자와 사소한 소멸자, 이런 종류 중 하나 또는 선행 형식이고 배열을cv-qualified 버전과 스칼라 타입, 클래스 형식을 가진 자동 저장 기간 따라 변화무쌍하는 범위에 있는 수준까지 범위에 없는 지점에서 jumps90 프로그램ill-formed 있다.d이니셜라이저 없이 닫힘(8.5).
90) a의 조건으로부터의 이전
switch
사례 라벨에 대한 진술은 이 점에서 점프로 간주된다.
그래서 교체int i = 4;
와 함께int i;
유효한 C++가 된다.
이게 무슨 소용이야?
그래. 만약 당신이 첫 번째 라벨 앞에 선언문을 붙인다면, 이것은 완벽하게 타당할 수 있다.
switch (a) {
int i;
case 0:
i = f(); g(); h(i);
break;
case 1:
i = g(); f(); h(i);
break;
}
선언과 문장의 규칙은 일반적으로 블록에 대해 공유되기 때문에, 그것은 또한 거기서도 문장이 가능하도록 허용하는 것과 같은 규칙이다.
또한 첫 번째 문장이 루프 구조인 경우 사례 라벨이 루프 본문에 나타날 수 있다는 점도 언급할 가치가 있다.
switch (i) {
for (;;) {
f();
case 1:
g();
case 2:
if (h()) break;
}
}
좀 더 읽기 쉬운 문장이 있다면 이렇게 코드를 쓰지 말아주십시오만, 완벽하게 유효하며, 또 그 문구는 다음과 같다.f()
통화할 수 있다
Duff's Device라는 유명한 용도가 있다.
int n = (count+3)/4;
switch (count % 4) {
do {
case 0: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
여기 다음에 가리키는 버퍼를 복사한다.from
에 의해 지목된 완충액까지.to
우리는 복사한다.count
자료의 예
그do{}while()
첫 번째 진술 전에 진술이 시작된다.case
, 라고 한다.case
라벨은 에 내장되어 있다.do{}while()
.
이렇게 하면 끝의 조건부 분기 수가 줄어든다.do{}while()
대략 4의 인수에 의해 마주치는 루프(이 예에서 상수는 원하는 값으로 조정될 수 있다).
이제, 최적화 도구들은 때때로 당신을 위해 이것을 할 수 있다(특히 그들이 스트리밍/벡터화된 지시를 최적화하고 있는 경우), 그러나 프로파일 안내 최적화 없이는 그들은 당신이 루프가 클 것으로 예상할지 아닐지 알 수 없다.
일반적으로 가변 선언은 그곳에서 발생할 수 있고 모든 경우에 사용될 수 있지만 스위치가 끝난 후에는 범위를 벗어난다.(초기화는 생략됨)
또한 스위치에 특유하지 않은 제어 흐름은 위에서 설명한 대로 스위치 블록의 해당 섹션으로 들어가거나goto
.
Linux에서 gcc를 사용한다고 가정할 경우 4.4 이전 버전을 사용 중이면 경고가 표시되었을 것이다.
-Wunreachable 코드 옵션은 gcc 4.4에서 이후 제거되었다.
가변 선언뿐 아니라 선진 점프도 가능하다.스파게티 코드가 잘 맞지 않는 경우에만 잘 활용할 수 있다.
int main()
{
int i = 1;
switch(i)
{
nocase:
printf("no case\n");
case 0: printf("0\n"); break;
case 1: printf("1\n"); goto nocase;
}
return 0;
}
인화
1
no case
0 /* Notice how "0" prints even though i = 1 */
스위치 케이스는 가장 빠른 제어 흐름 조항 중 하나라는 점에 유의해야 한다.그래서 프로그래머에게 매우 융통성이 있어야 하는데, 이런 경우는 가끔 있다.
유의해야 할 것은, 코드에 대한 구조적 제약이 사실상 없다는 점이다.switch
진술서, 또는 어디에case *:
라벨은 이 코드 안에 위치한다*.이는 더프의 장치와 같은 프로그래밍 기술을 가능하게 하며, 하나의 가능한 구현은 다음과 같다.
int n = ...;
int iterations = n/8;
switch(n%8) {
while(iterations--) {
sum += *ptr++;
case 7: sum += *ptr++;
case 6: sum += *ptr++;
case 5: sum += *ptr++;
case 4: sum += *ptr++;
case 3: sum += *ptr++;
case 2: sum += *ptr++;
case 1: sum += *ptr++;
case 0: ;
}
}
알다시피, 그 사이의 암호는switch(n%8) {
그리고case 7:
라벨은 확실히 도달할 수 있다...
으로서 슈퍼 고양이 고맙게도 모두 발언에서 신통한 발언:지적했다*99이후 가진 정권 goto도 라벨(는 경우*:라벨이나 다르지 않)은 초저공 선언이 포함된 선언의 범위 내에 나타날 수 있다.그래서 이 사건의 배치에 대한 구조적 제한만:라벨이 말하는 것은 정확하지 않습니다.하지만, 궁둥이의 장비 VLA긴 달려 있지 않는 99표준을 앞당겼다.그럼에도 불구하고, 나는 이 때문에 제 첫번째 문장에"사실상"를 삽입할 필요성을 절감했다.
필수 옵션과 관련된 답변을 받으셨습니다. -Wswitch-unreachable
경고를 생성하기 위해 이 답은 사용적합성/가치성 부분을 상세히 설명해야 한다.
에서 직접 인용하다.C11
, 챕터 제6.8.4.2, (내 것 중)
switch (expr) { int i = 4; f(i); case 0: i = 17; /* falls through into default code */ default: printf("%d\n", i); }
식별자가 (블록 내에) 자동 저장 지속 기간으로 존재하지만 초기화되지 않는 개체, 따라서 제어 식이 0이 아닌 값을 갖는 경우 에 대한 호출
printf
함수는 불확실한 값에 접근할 것이다.마찬가지로, 함수에 대한 호출f
손이 닿지 않다
그것은 매우 자기 설명적이다.이를 통해 에서만 사용할 수 있는 로컬 범위 변수를 정의할 수 있다.switch
진술 범위
"루프 반"을 구현하는 것이 비록 최선의 방법은 아닐 수 있지만 가능하다.
char password[100];
switch(0) do
{
printf("Invalid password, try again.\n");
default:
read_password(password, sizeof(password));
} while (!is_valid_password(password));
참조URL: https://stackoverflow.com/questions/41727415/valid-but-worthless-syntax-in-switch-case
'IT이야기' 카테고리의 다른 글
컨트롤러에서 Axios 캐치 섹션으로 json 응답 읽기 - Laravel Vue Axios (0) | 2022.05.10 |
---|---|
Visual Studio 디버거 오류:프로그램을 시작할 수 없음 지정된 파일을 찾을 수 없음 (0) | 2022.05.09 |
문자열을 특정 위치에 삽입하는 방법 (0) | 2022.05.09 |
사용자가 Laravel에서 인증된 경우 Vue 구성 요소를 체크인하는 방법 (0) | 2022.05.09 |
구성 요소에 이벤트 수신기가 연결되어 있는지 확인하십시오. (0) | 2022.05.09 |