当前位置: C语言 -- 基础 -- 语句和块

语句和块(三)

六、选择语句

选择语句(selection statements)根据控制表达式的值在一组次块代码中选择执行。C语言中选择语句包括if语句和switch语句。


1、if语句

if语句存在以下两种语法格式:

if( controlling-expression ) secondary-block
if( controlling-expression ) secondary-block else secondary-block

其中controlling-expression是控制表达式,if语句中控制表达式应具有标量类型(scalar type);secondary-block是次块;ifelseC语言关键词。


if语句流程图如下所示:

if语句流程图


if else语句流程图如下所示:

if_else语句流程图


如果if语句控制表达式的值不等于0,将执行第一个次块;如果if语句控制表达式的值等于0,将执行第二个次块。

int i = 1;

if(i<0)
    puts("i is less than 0.");  //该语句不会执行。

if(i<3)
    puts("i is less than 3.");  //该语句会执行。
else
    puts("i is greater than or equal to 3.");   //该语句不会执行。

if语句中如果第一个次块是通过标签到达的,第二个次块不会被执行。

int i = 1;

if(i<0)
{
    here :
    puts("i is less than 0.");
}
else
    puts("i is greater than or equal to 0.");

i += -2;

if(i==-1)
    goto here;

将输出:

i is greater than or equal to 0.
i is less than 0.

else与语法上允许的、代码文本中else之前最靠近的if匹配。

if(expression)  //A
    if(expression)  //B
        statements
    else    //else与B处的if匹配。
        statements

上述代码等价于:

if(expression)
{
    if(expression)
        statements
    else
        statements
}

可以使用大括号({ })改变语法结构。

if(expression)  //A
{
    if(expression)  //B
        statements
}
else    //else与A处的if匹配。
    statements

2、switch语句

switch语句具有以下语法格式:

switch( controlling-expression ) secondary-block

其中controlling-expression是控制表达式,switch语句中控制表达式应具有整数类型;secondary-block是次块;switchC语言关键词。


switch语句流程图如下所示:

switch语句流程图


switch语句中的控制表达式会执行整数提升(integer promotions);每个case标签中的常量表达式应为整型常量表达式,会转换成控制表达式提升后的类型。如果转换后的值与提升后的控制表达式的值匹配,程序执行将跳转到匹配的case标签后的语句或者声明;如果不存在匹配的case标签,但存在default标签,程序执行将跳转到default标签后的语句或者声明。

switch(i)
{
    case 1 :
        puts("The value of i is 1.");
        break;
    case 2 :
        puts("The value of i is 2.");
        break;
    default :
        puts("The value of i is unknown.");
        break;
}

如果i的值为1,将执行与case 1相关联的次块,与case 2default相关联的次块不会被执行;如果i的值为2,将执行与case 2相关联的次块,与case 1default相关联的次块不会被执行;如果i的值为其它值,将执行与default相关联的次块,与case 1case 2相关联的次块不会被执行。


如果不存在匹配的case常量表达式,并且不存在default标签,switch语句中的任何部分都不会执行。

int i = 3;

//switch语句中的任何部分都不会执行。
switch(i)
{
    case 1 :
        puts("The value of i is 1.");
        break;
    case 2 :
        puts("The value of i is 2.");
        break;
}

转换后同一switch语句中的所有case常量表达式的值应不同,并且同一switch语句最多只能存在一个default标签。

//存在两个相同值的case常量表达式,switch语句非法。
switch(i)
{
    case 0 :
        puts("The value of i is 0.");
        break;
    case false :
        puts("The value of i is false.");
        break;
    default :
        break;
}

//不存在default标签,但switch语句是合法的。
switch(i)
{
    case 0 :
        puts("The value of i is 0.");
        break;
    case 1 :
        puts("The value of i is 1.");
        break;
}

对于嵌套的switch语句,外层switch语句和内层switch语句可以存在各自的default标签;并且内层case常量表达式的值可以与外层case常量表达式的值相同。

struct {
    int i1;
    int i2;
} s = {1, 1};

switch(s.i1)
{
    case 0 :
        puts("The value of s.i1 is 0.");
        break;
    case 1 :
        puts("The value of s.i1 is 1.");

        switch(s.i2)
        {
            case 0 :
                puts("The value of s.i2 is 0.");
                break;
            case 1 :
                puts("The value of s.i2 is 1.");
                break;
            default :
                break;
        }

    default :
        break;
}

如果switch语句的任一case标签或者default标签位于可变修改类型(variably modified type)标识符的作用域内,整个switch语句应在该标识符的作用域内;即可变修改类型标识符应在switch语句前声明,或者在switch语句最后一个标签(最后一个标签可以是case标签,也可以是default标签。)后声明。

int n = 3;
int x = 2;

int a1[n]; //声明合法。

switch(x)
{
    int a2[n];  //声明非法。

    case 0 :
        int a3[n];  //声明非法。
        break;
    case 1 :
        int a4[n];  //声明非法。
        break;
    default :
        int a5[n];  //声明合法。
        break;

    int a6[n];  //声明合法。
}

int a7[n];  //声明合法。

可变修改类型对象的存储空间通常在其作用域开始时分配,其作用域结束时释放。如果switch语句的case标签或者default标签跳过可变修改类型对象的定义,直接进入其作用域,将会导致未定义行为。