例如:
#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
只是好奇。这是技术限制吗?
人们似乎认为只有一个常量指针表达式。但这真的是真的吗?例如,这是 Objective-C 中的一个常见范例(除了
NSString
、id
和 nil
之外,它实际上只是 C,它们只是一个指针,所以它仍然是相关的 - 我只是想指出事实上,它有 is,尽管这只是一个技术问题):
#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
原因似乎是 switch 只允许整数值(如编译器警告所述)。所以我想更好的问题是问为什么会出现这种情况? (尽管现在可能为时已晚。)
开关将变量与一组编译时常量进行比较。除了 null 之外,我看不到任何可以与指针进行比较的有效编译时常量。例如:
switch (ptr) {
case &var1: printf ("Pointing to var1"); break;
case &var2: printf ("Pointing to var2"); break;
}
var1 和 var2 在程序的每次运行中可能不同,并且不会是编译时常量。一种可能性可能是它们是始终固定的内存映射端口的地址,但否则我不知道如何轻松地从两种情况(空/非空)中扩展它。
鉴于仅存在单个常量指针表达式,因此
switch
语句几乎无法提供指针表达式。您基本上引用了唯一可能的构造。
Switch 语句仅对整数值进行操作。这就是为什么错误消息是“开关数量不是整数”。我不认为这是技术限制,因为它超出了语言语法。
switch
语句仅对整数表达式进行操作。 指针不是整型表达式。
如果愿意,您可以将指针显式转换为整型,但建议的代码有点奇怪和不自然。
所以准确回答你的问题:因为指针和整型之间没有隐式转换。
将 ptr 转换为 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 的情况。 您可以转换为 intptr_t,但是当您只有一个可以比较的东西时,这仍然是无意义的。
switch
语句的存在是因为编译器通常可以将它们转换为
跳转表,如果你的case标签是连续的整数,这个概念最有效。 但在指针转换为整型的情况下,除了更麻烦的语法之外,使用 switch 与
if
/ else
相比,你没有任何收获。
case
需要是编译时常量,而指针(大多数时候)是在链接时确定的。因此,
switch
不支持指针是有道理的。joshua 这不是在 switch 中合法使用指针。
如果您确实必须使用 switch 语句,则将其强制转换为 _int64 或 long long 或某些保证与指针一样大或更大的整型类型(取决于编译器)。
此外,某些编译器可能会将 switch 的最大大小限制为 int 或其他任意大小。在这种情况下你根本不能使用 switch 语句。
直流电
可以打开指针。
void why_cant_we_switch_him(void *ptr)
{
switch ([ptr intValue]) {
case NULL:
printf("NULL!\n");
break;
default:
printf("%p!\n", ptr);
break;
}
}