为什么不切换指针?

例如:

#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, idnil ,它们只是一个指针,所以它仍然相关 – 我只想指出实际上有虽然这只是一个技术问题,但它是常见的用途):

 #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; } }