为什么没有打开指针?

问题描述 投票:0回答:13

例如:

#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 只允许整数值(如编译器警告所述)。所以我想更好的问题是问为什么会出现这种情况? (尽管现在可能为时已晚。)

c pointers switch-statement
13个回答
16
投票

开关将变量与一组编译时常量进行比较。除了 null 之外,我看不到任何可以与指针进行比较的有效编译时常量。例如:

switch (ptr) { 
   case &var1: printf ("Pointing to var1"); break;
   case &var2: printf ("Pointing to var2"); break;
}

var1 和 var2 在程序的每次运行中可能不同,并且不会是编译时常量。一种可能性可能是它们是始终固定的内存映射端口的地址,但否则我不知道如何轻松地从两种情况(空/非空)中扩展它。


13
投票

因为常量指针表达式只有一个

鉴于仅存在单个常量指针表达式,因此

switch
语句几乎无法提供指针表达式。您基本上引用了唯一可能的构造。


12
投票

Switch 语句仅对整数值进行操作。这就是为什么错误消息是“开关数量不是整数”。我不认为这是技术限制,因为它超出了语言语法。


8
投票

switch
语句仅对整数表达式进行操作。 指针不是整型表达式。

如果愿意,您可以将指针显式转换为整型,但建议的代码有点奇怪和不自然。

所以准确回答你的问题:因为指针和整型之间没有隐式转换。


6
投票

将 ptr 转换为 int 并重试:

switch( (int)ptr )

或者更正确的是:

switch( (intptr_t)ptr ) // C99 integer type to hold a pointer

5
投票

你可以(如果你真的必须的话)。只需将指针转换为“适当大小”的整数即可。 为此,应使用 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; }



2
投票
case

标签需要一个常量表达式,通常是一个整数,而指针往往不能很好地与这些表达式进行比较,除非是 NULL 的情况。 您可以转换为 intptr_t,但是当您只有一个可以比较的东西时,这仍然是无意义的。


switch

语句的存在是因为编译器通常可以将它们转换为

跳转表
,如果你的case标签是连续的整数,这个概念最有效。 但在指针转换为整型的情况下,除了更麻烦的语法之外,使用 switch 与 if /
else
相比,你没有任何收获。
    


1
投票


0
投票


0
投票
case

需要是编译时常量,而指针(大多数时候)是在链接时确定的。因此,

switch
不支持指针是有道理的。
    


-1
投票

joshua 这不是在 switch 中合法使用指针。

如果您确实必须使用 switch 语句,则将其强制转换为 _int64 或 long long 或某些保证与指针一样大或更大的整型类型(取决于编译器)。

此外,某些编译器可能会将 switch 的最大大小限制为 int 或其他任意大小。在这种情况下你根本不能使用 switch 语句。

直流电


-1
投票
可以打开指针。


-3
投票

void why_cant_we_switch_him(void *ptr) { switch ([ptr intValue]) { case NULL: printf("NULL!\n"); break; default: printf("%p!\n", ptr); break; } }

	
© www.soinside.com 2019 - 2024. All rights reserved.