在C++中开启常量是否合法?

4

我刚刚意识到我引入了一个错误,让我惊讶的是它编译通过了,使用常量开关是合法的吗?

Visual Studio 8和Comeau都接受它(没有警告)。

switch(42) { // simplified version, this wasn't a literal in real life
    case 1:
        std::cout << "This is of course, imposible" << std::endl;  
}

4
尝试使用/W4编译,它会输出警告信息。我也建议始终使用W4编译 ;) - lx.
你应该把这个放在回答里,因为它回答了真正的问题(为什么没有被捕捉到)。 - Dave Van den Eynde
1
使用W4编译15年前未经W4编译的代码库存在一些问题。 - Thomas L Holaday
3
为什么这应该是“非法”的?虽然你可能不想这样做,但一个优秀的编译器应该会给你一个警告,但没有理由禁止这样做。但模板代码或生成的代码可能会轻松地产生这样的构造。 - j_random_hacker
也许你把它和这个搞混了:switch(x) { case 1: ...; case 1: ...; }(同一个case出现两次)? - Johannes Schaub - litb
2
Thomas,这些问题可能需要解决。不使用W4编译不会解决它们。 - Dave Van den Eynde
6个回答

18

打开常量可能是有意义的,这并非不可能。考虑以下情况:

void f( const int x ) {
   switch( x ) {   
   ...
   }
}

将文字常量作为开关很少有意义,但是是合法的。

编辑:仔细思考后,还是有一种情况可以使用文字常量作为开关:

int main() {
    switch( CONFIG ) {
           ...
    }
}

该程序是使用以下编译的:

g++ -DCONFIG=42 foo.cpp

1
+1,好的例子。此外,模板代码或生成的代码可以轻松地产生这样的结构。 - j_random_hacker

16

不是所有对编译器有意义的东西都有意义!

以下内容也可以被编译,但没有意义:

if (false)
{
   std::cout << "This is of course, imposible" << std::endl;
}

作为开发人员,发现这些问题取决于我们自己。


@Chris: #define DEBUG false ... 然后 ... if (DEBUG) { fprintf(stderr, "DEBUG: 你不可能到达这里,一个好的优化编译器会删除整个代码块。")} - corlettk
我曾经看到过这样的代码被滥用:for(....) { if(false) { end: ....; } .... if(stuff) goto end; } - Johannes Schaub - litb

3

这种做法是合法的一个好理由是编译器可能会在编译时解析这个值,这取决于你处于开发的哪个阶段。

例如,在调试代码时,你可能会使用类似以下的方法:

int glyphIndex;
...
#if CHECK_INVALID_GLYPH
glyphIndex = -1;
#endif

switch (glyphIndex)
    ...

编译器确定glyphIndex在此处为-1,因此它就像一个常量一样好。或者你可以这样编写代码:
#if CHECK_INVALID_GLYPH
const int glyphIndex = -1;
#else
int glyphIndex = GetGlyph();
#endif

您不会真正想改变switch语句的主体,仅仅是为了做一些小修改,编译器完全有能力对代码进行优化,消除永远不会执行的部分。


2
是的,这是合法的。

2

是的,任何整数表达式都可以合法地进行切换。这与经常使用的使用函数返回的整数值进行switch的构造相同。


2

是的,但为什么你想要这样做(除非是调试)是另一回事。

这类似于if (0)while (true)


4
但是使用带有break的while(true)结构是相当常见的构造。 - ChrisF
while(true) 并不像看起来那么疯狂,它是一些结构的基础,虽然可能有更好的方法,但它确实被使用。if(0) 或 if(false) 则完全属于“为什么要这样做?”的阵营 :) - Lazarus
我只是在演示switch/loop语句中的字面常量并不罕见。 - graham.reeds
懂行的人总是使用 for(;;) { ... } 而不是 while(1) { ... },以避免编译器警告“常量条件”。 - Johannes Schaub - litb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接