C语言 为什么不打开指针?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2308323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:34:40  来源:igfitidea点击:

Why no switch on pointers?

cpointersswitch-statement

提问by Michael

For instance:

例如:

#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

Just curious. Is this a technical limitation?

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

EDIT

编辑

People seem to think there is only one constant pointer expression. Is that is really true, though? For instance, here is a common paradigm in Objective-C (it is really only C aside from NSString, idand nil, which are merely a pointers, so it is still relevant —?I just wanted to point out that there is, in fact, a common use for it, despite this being only a technical question):

人们似乎认为只有一种常量指针表达式。然而,这是真的吗?举例来说,这里是在Objective-C(一种常见的范例是真的是仅含有C除了NSStringid并且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

It appears that the reason is that switch only allows integral values (as the compiler warning said). So I suppose a better question would be to ask why this is the case? (though it is probably too late now.)

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

采纳答案by Jeff Kelley

Switch statements operate on integral values only. That's why the error message is "switch quantity not an integer." I don't think it's a technical limitation so much as it's outside the language syntax.

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

回答by DigitalRoss

Because there is only one constant pointer expression

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

Given that only a single constant pointer expression exists, the switchstatement has little to offer pointer expressions. You have cited essentially the only possible construction.

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

回答by Tarydon

A switch compares the variable with a set of compile-timeconstants. Other than null, I can't see any valid compile time constants that you might compare a pointer with. For example:

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

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

var1 and var2 are likely different in each run of the program, and would not be compile time constants. One possibility might be that they are addresses of memory-mapped ports that are always fixed, but otherwise I don't see how you could easily expand this from your two cases (null / not-null).

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

回答by Brian R. Bondy

switchstatements operate on integral expressions only. A pointer is not an integral expression.

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

You can explicitly convert a pointer to an integral type if you wanted to, but the proposed code is a little strange and unnatural.

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

So to answer your question exactly: Because there is no implicit conversion between a pointer and an integral type.

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

回答by Justicle

Cast ptr to an int and try again:

将 ptr 转换为 int 并重试:

switch( (int)ptr )

or to be more correct:

或者更正确:

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

回答by Clifford

You can (if you really must). Simply cast the pointer to an appropriately sizedinteger. For this intptr_tshould be used. That is not to say I'd recommend it, but you may have your reasons.

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

回答by Dan Olson

caselabels expect a constant-expression, usually an integer, and pointers tend not to compare well against these except in the case of NULL. You could cast to intptr_t, but it's still nonsensical when you only have one thing you can compare against.

case标签期望一个常量表达式,通常是一个整数,并且指针往往不能很好地与这些进行比较,除非是 NULL 的情况。您可以转换为 intptr_t,但是当您只有一件事可以进行比较时,这仍然是荒谬的。

switchstatements exist because the compiler can often turn them into a jump table, which is a concept that works best if your case labels are consecutive integers. But in the case of a pointer casted to integral type, you gain nothing over an if/ elseby using switch except a more cumbersome syntax.

switch语句存在是因为编译器通常可以将它们转换为跳转表,如果您的案例标签是连续整数,这是一个最有效的概念。但是在指针转换为整数类型的情况下,除了更麻烦的语法之外,使用 switch对if/没有任何好处else

回答by Otávio Décio

It can be related to how switch is implemented - it seems to expect at most an integer so it can use a certain CPU register which might not be possible with a pointer.

它可能与 switch 的实现方式有关 - 它似乎最多期望一个整数,因此它可以使用某个 CPU 寄存器,而指针可能无法使用该寄存器。

回答by DeveloperChris

Doh! why even use a switch statement? switch statements should only be used if you have 3 or more options to choose from if you have 2 options then use an if(){} else {} statement.

哦!为什么甚至使用 switch 语句?仅当您有 3 个或更多选项可供选择时才应使用 switch 语句,如果您有 2 个选项,则应使用 if(){} else {} 语句。

joshua this is not a legitimate use of a pointer in a switch.

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

If you really must use a switch statement then cast it to an _int64 or long long or some integral type guaranteed to be as big as or bigger than a pointer (depends on compiler).

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

Also some compilers may limit the maximum size of a switch to an int or some other arbitrary size. in this case you can't use a switch statement at all.

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

DC

直流电

回答by mlouk

enum boolean
{
 FALSE=0,
 TRUE=!FALSE
}boolean;
...
void *ptr=NULL;
...
switch((!ptr))
{
 case FALSE:
  ...
  break;
 case TRUE:
  ...;
  break;
}
...

It's possible to switch on pointer.

可以打开指针。