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
Why no switch on pointers?
提问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除了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
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.
可以打开指针。

