使用C switch语句进行错误处理

时间:2009-06-10 12:54:07

标签: c error-handling goto

考虑这个在实际工作之前检查错误的C结构:

int function(struct Context *context,struct Connection *conn)
{
    int retval;

    switch(0)
    {   
        case 0:
            retval = BUFFER_INACTIVE;
            if(conn->mSocket == -1) 
                break;
            retval = BUFFER_FULL;
            /* Is there enough room to add ? */
            if((context->mMaxBufferSize - conn->mSendPacketLength) < aPacketLength)
                break;

            /* Is the send packet buffer half sent? */
            if(conn->mSendPacketLength > 0 && conn->mSendPacketPos != conn->mSendPacket)
                break;

            /* Do some work here */
            retval = BUFFER_DONE;
    }
    /* Do some things before returning */
    printf("%d",retval);
    return retval;
}

你认为这是可读的吗?使用goto或堆叠if()的替代方案会更好吗?

5 个答案:

答案 0 :(得分:5)

我从未见过切换解决方案,但我做过这样的事情:

do {
    err = func();
    if( err ) break;
    err = func2();
    if( err ) break;
    ...
} while( 0 );
if( err ) {
   // handle errors
}

但是这和它之间的真正区别是什么:

err = func();
if( err ) goto done;
err = func2();
if( err ) goto done;
...
done:
if( err ) {
   //handle errors;
}

第一个是第二个重写,以避免使用关键字goto,我认为goto解决方案更具可读性。我花了一段时间,但我设法让自己相信goto不是总是邪恶。

最后,如果可能的话,我更喜欢使用if语句,因为它使代码更具可读性,但如果需要,则goto

答案 1 :(得分:4)

我会说那不太可读。我认为使用if语句甚至是goto将是一种更合适的方法。使用goto不是世界末日,完全可以接受并适合错误处理。

http://kerneltrap.org/node/553/2131

答案 2 :(得分:0)

我建议您使用 while(true)而不是switch:

while(true)
{   
            retval = BUFFER_INACTIVE;
            if(conn->mSocket == -1) 
                    break;
            retval = BUFFER_FULL;
            /* Is there enough room to add ? */
            if((context->mMaxBufferSize - conn->mSendPacketLength) < aPacketLength)
                    break;

            /* Is the send packet buffer half sent? */
            if(conn->mSendPacketLength > 0 && conn->mSendPacketPos != conn->mSendPacket)
                    break;

            /* Do some work here */
            retval = BUFFER_DONE;
            break;
}

答案 3 :(得分:0)

另一种选择是将它包装在一个函数中并返回而不是破坏。这通常是一个坏主意,因为它最终会添加一个不必要的抽象层。但是,在某些情况下,它可以使事情变得更简单。

答案 4 :(得分:-1)

另一种方法是使用级联ifs:

u8 u8IsOk;

u8IsOk = Func1();

if(u8IsOk)
{
    /* Do some stuff...*/
    u8IsOk = Func2();
} /* if */

if(u8IsOk)
{
    /* Do some stuff...*/
    u8IsOk = Func3();
} /* if */

......等等。不如其他一些方法有效,但避免过多的嵌套,转到,中断,while(0)和多次返回。