왜 포인터를 켜지 않습니까?
예를 들어 다음과 같습니다.
#include <stdio.h>
void why_cant_we_switch_him(void *ptr)
{
switch (ptr) {
case NULL:
printf("NULL!\n");
break;
default:
printf("%p!\n", ptr);
break;
}
}
int main(void)
{
void *foo = "toast";
why_cant_we_switch_him(foo);
return 0;
}
gcc test.c -o test
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values
그냥 궁금해요.이것이 기술적인 제한입니까?
편집
사람들은 일정한 포인터 표현이 하나밖에 없다고 생각하는 것 같습니다.하지만 그게 정말로 사실입니까?를 들어,인 패러다임이 어기인이다은하고는로를의은하고는mcr로c를tny를ye,ese어se ).NSString
,id
그리고.nil
, 이는 단순한 포인터이므로 여전히 관련성이 있습니다. 기술적인 문제임에도 불구하고 실제로 공통적으로 사용되는 부분이 있음을 지적하고 싶었습니다.)
#include <stdio.h>
#include <Foundation/Foundation.h>
static NSString * const kMyConstantObject = @"Foo";
void why_cant_we_switch_him(id ptr)
{
switch (ptr) {
case kMyConstantObject: // (Note that we are comparing pointers, not string values.)
printf("We found him!\n");
break;
case nil:
printf("He appears to be nil (or NULL, whichever you prefer).\n");
break;
default:
printf("%p!\n", ptr);
break;
}
}
int main(void)
{
NSString *foo = @"toast";
why_cant_we_switch_him(foo);
foo = kMyConstantObject;
why_cant_we_switch_him(foo);
return 0;
}
gcc test.c -o test -framework Foundation
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values
그 이유는 (컴파일러 경고가 말한 것처럼) 스위치가 적분값만 허용하기 때문인 것 같습니다.그래서 더 좋은 질문은 왜 이런 일이 발생하는지 묻는 것이라고 생각합니다.(지금은 아마 너무 늦었을 겁니다.)
스위치는 이 변수를 컴파일 시간 상수 집합과 비교합니다.null을 제외하고 포인터와 비교할 수 있는 유효한 컴파일 시간 상수를 찾을 수 없습니다.예를 들어,
switch (ptr) {
case &var1: printf ("Pointing to var1"); break;
case &var2: printf ("Pointing to var2"); break;
}
var1과 var2는 프로그램의 각 실행마다 다르며 컴파일 시간 상수가 아닐 가능성이 높습니다.한 가지 가능성은 항상 고정되어 있는 메모리 매핑 포트의 주소일 수 있지만, 그렇지 않은 경우에는 두 가지 경우(null / not-null)에서 어떻게 쉽게 확장할 수 있는지 알 수 없습니다.
일정한 포인터 식이 하나밖에 없기 때문에
하면, 만 할 할,switch
expressionsstatement를 제공하지 .당신은 근본적으로 유일하게 가능한 공사를 언급했습니다.
스위치 문은 적분값에서만 작동합니다.그래서 오류 메시지가 "정수가 아닌 스위치 수량"입니다.언어 구문을 벗어난 것이기 때문에 기술적인 제한은 아니라고 생각합니다.
switch
문장은 적분식에서만 작동합니다.포인터는 필수 표현이 아닙니다.
당신이 원한다면 포인터를 명시적으로 통합형으로 변환할 수 있지만, 제안된 코드는 조금 이상하고 부자연스럽습니다.
질문에 정확하게 답변해 드리겠습니다.포인터와 적분형 사이에는 암시적 변환이 없기 때문입니다.
tr을 int에 던지고 다시 시도해 보십시오.
switch( (int)ptr )
더 정확하게 말하면 다음과 같습니다.
switch( (intptr_t)ptr ) // C99 integer type to hold a pointer
(꼭 그래야 한다면) 할 수 있습니다.포인터를 적절한 크기의 정수에 맞추기만 하면 됩니다.이거는intptr_t
사용해야 합니다.그렇다고 제가 추천하고 싶은 건 아니지만, 이유가 있을 수도 있습니다.
#include <stdint.h>
#include <stdio.h>
void we_can_switch_him(void *ptr)
{
switch ((intptr_t)ptr) {
case (intptr_t)NULL:
printf("NULL!\n");
break;
default:
printf("%p!\n", ptr);
break;
}
}
int main(void)
{
void *foo = "toast";
we_can_switch_him(foo);
return 0;
}
case
레이블은 일반적으로 정수인 상수 표현을 기대하며, 포인터는 NULL의 경우를 제외하고는 이들과 잘 비교되지 않는 경향이 있습니다. inttr_t에 캐스트할 수 있지만 비교할 수 있는 것이 한 가지뿐인 경우에는 여전히 무의미합니다.
switch
컴파일러가 점프 테이블로 변환할 수 있기 때문에 문장이 존재합니다. 점프 테이블은 대소문자 레이블이 연속 정수일 경우 가장 효과적인 개념입니다.그러나 적분형으로 주조된 포인터의 경우, 당신은 다음과 같은 것을 얻을 수 없습니다.if
/else
좀 더 번거로운 구문을 제외하고는 스위치를 사용합니다.
스위치를 구현하는 방법과 관련이 있을 수 있습니다. 포인터로는 불가능할 수도 있는 특정 CPU 레지스터를 사용할 수 있도록 최대 정수를 기대할 수 있는 것입니다.
정답을 정확히 맞추는 것은 스위치 문이 비교할 수 있는 컴파일 시간이 필요하기 때문입니다.런타임 데이터를 사용할 수 있다면 이렇게 해야 할 이유가 많이 보입니다.특히, 내 기능 포인터가 가리키는 기능이 무엇인지 알고 싶다고 하세요.스위치 구조는 다른 if 문들보다 훨씬 우아합니다.
Doh! switch 문을 사용하는 이유는 무엇입니까? switch 문은 옵션이 2개인 경우 선택할 수 있는 옵션이 3개 이상 있는 경우에만 사용해야 하며 if(){}개 이외의 {}개 문을 사용해야 합니다.
Joshua 이것은 스위치에서 포인터를 합법적으로 사용하는 것이 아닙니다.
만약 당신이 정말로 스위치 문을 사용해야 한다면, 그것을 _int64 또는 long 또는 포인터만큼 크거나 클 것이 보장되는 어떤 적분 타입에 캐스팅하세요 (컴파일러에 따라).
또한 일부 컴파일러는 스위치의 최대 크기를 int 또는 다른 임의 크기로 제한할 수도 있습니다.이 경우 스위치 문을 전혀 사용할 수 없습니다.
DC
enum boolean
{
FALSE=0,
TRUE=!FALSE
}boolean;
...
void *ptr=NULL;
...
switch((!ptr))
{
case FALSE:
...
break;
case TRUE:
...;
break;
}
...
포인터를 켤 수 있습니다.
이 변경 사항은 스위치에서만 필요합니다. [ptrintValue]
void why_cant_we_switch_him(void *ptr)
{
switch ([ptr intValue]) {
case NULL:
printf("NULL!\n");
break;
default:
printf("%p!\n", ptr);
break;
}
}
언급URL : https://stackoverflow.com/questions/2308323/why-no-switch-on-pointers
'programing' 카테고리의 다른 글
맨 위 탐색 모음 페이지의 맨 위 내용 (0) | 2023.09.11 |
---|---|
presentModalViewController를 사용하여 투명 뷰를 만드는 방법 (0) | 2023.09.11 |
엔티티 프레임워크를 사용하여 Oracle DB에 쿼리할 때 오류 "ORA-00933"이 발생하는 경우가 있지만 웹 앱을 재시작하면 작동합니다. (0) | 2023.09.11 |
CSS로 이미지를 그레이아웃하시겠습니까? (0) | 2023.09.11 |
NSParameterAssert란? (0) | 2023.09.11 |