为什么不切换指针?

Mic*_*ael 28 c pointers switch-statement

例如:

#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
Run Code Online (Sandbox Code Playgroud)

只是好奇.这是技术限制吗?

编辑

人们似乎认为只有一个常量指针表达式.这是真的吗?举例来说,这里是在Objective-C(一种常见的范例是真的是仅含有C除了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
Run Code Online (Sandbox Code Playgroud)

看来原因是switch只允许整数值(如编译器警告所说).所以我想更好的问题是问为什么会这样?(虽然现在可能已经太晚了.)

Dig*_*oss 13

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

鉴于只存在一个常量指针表达式,该switch语句几乎没有提供指针表达式.你基本上引用了唯一可能的结构.

  • 具有静态存储持续时间的变量的地址也是常量. (6认同)
  • 你可以有一个其他常量指针表达式,如"char*vgabuffer =(char*)(0xB800)" (3认同)
  • 投反对票是因为粗体声明不清楚,没有解释,而且似乎是错误的。你是什​​么意思“只有一个常量指针表达式”?如果只有一个,你为什么不告诉我们它是什么?...正如@oyvind 指出的那样,内存映射外设位于恒定地址 - 因此,根据我对含义的最佳猜测,我的“似乎是错误的”。 (3认同)
  • 巴姆.这似乎是原因.我不确定为什么它几乎逃脱了其他所有切换常数操作的案例. (2认同)
  • 开关中的指针在处理微控制器中的内存映射外设时很有用。 (2认同)

Jef*_*ley 9

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


Bri*_*ndy 8

switch语句仅对整数表达式起作用.指针不是整数表达式.

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

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


Tar*_*don 8

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

switch (ptr) { 
   case &var1: printf ("Pointing to var1"); break;
   case &var2: printf ("Pointing to var2"); break;
}
Run Code Online (Sandbox Code Playgroud)

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


Jus*_*cle 7

将ptr转换为int并再试一次:

switch( (int)ptr )
Run Code Online (Sandbox Code Playgroud)

或者更正确:

switch( (intptr_t)ptr ) // C99 integer type to hold a pointer
Run Code Online (Sandbox Code Playgroud)

  • @Dan:不,你能想到的唯一比较*是零. (5认同)
  • 这仅适用于目标平台上的`sizeof(int)== sizeof(ptr)`.情况并非总是如此. (2认同)
  • 你无法保证`int`足够大以容纳指针. (2认同)

Cli*_*ord 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;
}
Run Code Online (Sandbox Code Playgroud)