为什么不切换指针?
例如:
#include 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
只是好奇。 这是技术限制吗?
编辑
人们似乎认为只有一个常量指针表达式。 这是真的吗? 例如,这是Objective-C中的一个常见范例(除了NSString
,它实际上只有C, id
和nil
,它们只是一个指针,所以它仍然相关 – 我只想指出实际上有虽然这只是一个技术问题,但它是常见的用途):
#include #include 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
看来原因是switch只允许整数值(正如编译器警告所说)。 所以我想更好的问题是问为什么会这样? (虽然现在可能已经太晚了。)
Switch语句仅对整数值进行操作。 这就是为什么错误消息是“切换数量不是整数”。 我不认为这是技术限制,因为它超出了语言语法。
因为只有一个常量指针表达式
鉴于只存在一个常量指针表达式, switch
语句几乎没有提供指针表达式。 你基本上引用了唯一可能的结构。
switch
语句仅对整数表达式进行操作。 指针不是整数表达式。
如果您愿意,可以显式地将指针转换为整数类型,但建议的代码有点奇怪且不自然。
所以要准确回答你的问题:因为指针和整数类型之间没有隐式转换。
将ptr转换为int并再试一次:
switch( (int)ptr )
或者更正确:
switch( (intptr_t)ptr ) // C99 integer type to hold a pointer
开关将变量与一组编译时常量进行比较。 除了null之外,我看不到任何可以比较指针的有效编译时常量。 例如:
switch (ptr) { case &var1: printf ("Pointing to var1"); break; case &var2: printf ("Pointing to var2"); break; }
var1和var2在程序的每次运行中可能都不同,并且不是编译时常量。 一种可能性是它们是总是固定的内存映射端口的地址,但是我不知道如何从两种情况(null / not-null)中轻松扩展它。
你可以(如果你真的必须)。 只需将指针强制转换为适当大小的整数即可。 对于这个intptr_t
应该使用。 这并不是说我推荐它,但你可能有你的理由。
#include #include 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之外,指针往往不能很好地与它们进行比较。 你可以转换为intptr_t,但是当你只有一件可以比较的东西时,它仍然是荒谬的。
存在switch
语句是因为编译器经常可以将它们变成跳转表 ,如果你的case标签是连续的整数,这个概念最有效。 但是在指针转换为整数类型的情况下,除了更麻烦的语法之外,使用switch除了if
/ else
之外什么都没有。
它可能与交换机的实现方式有关 – 它似乎最多需要一个整数,因此它可以使用某个CPU寄存器,这可能是指针无法实现的。
卫生署! 为什么甚至使用switch语句? 如果你有3个或更多选项可供选择,如果你有2个选项,那么只应使用switch语句,然后使用if(){} else {}语句。
约书亚这不是交换机中指针的合法使用。
如果你真的必须使用switch语句然后将它转换为_int64或long long或某种整数类型,保证与指针一样大或大于指针(取决于编译器)。
一些编译器也可能将开关的最大大小限制为int或其他任意大小。 在这种情况下,你根本不能使用switch语句。
DC
enum boolean { FALSE=0, TRUE=!FALSE }boolean; ... void *ptr=NULL; ... switch((!ptr)) { case FALSE: ... break; case TRUE: ...; break; } ...
可以打开指针。
您只需要在开关中进行此更改:[ptr intvlue]
void why_cant_we_switch_him(void *ptr) { switch ([ptr intvalue]) { case NULL: printf("NULL!\n"); break; default: printf("%p!\n", ptr); break; } }