C – How to Return an Error from a Boolean Function

booleancerror handling

I'm working on a little pet program in C where I have a game board that consists of a bunch of squares:

typedef struct _square {
    bool checked;
} Square;

typedef struct _board {
    Square *squares;
    uint8_t width;
    uint8_t height;
} Board;

I don't want these structs to be visible to the public, so instead I want to write a simple function that checks if a square is checked or not, called square_is_checked. It makes sense for the return type to be a bool (I'm assuming C99 here).

bool square_is_checked(Board *b, uint8_t row, uint8_t col)
{
    return b->squares[(uint16_t)row * b->height + col].checked;
}

However, it's possible that a NULL pointer, or a row and column that don't exist could be passed as arguments. So I want to add some simple checks:

bool square_is_checked(Board *b, uint8_t row, uint8_t col)
{
    if (!b) { return ???; }
    if (row >= b->height || col >= b->width) { return ???; }
    return b->squares[(uint16_t)row * b->height + col].checked;
}

However, a bool is either true or false — no room for error management. What's considered best practice here (e.g., do I have to rewrite this function to pass a pointer to a bool)?

Best Answer

This isn't really about how to return bool from a function in C. Your code already does that.

The question really is, is bool the right data type when the set of possible values is larger than true and false. That could be the subject of a lengthy philosophical discussion, but as this is a personal project, you don't need to worry about your decision within a larger context. On a team, where existing code might already have an opinion on situations like this, a decision might be made for you.

So in this case, there are many couple possible answers. A few options:

  • Keep the bool return type, and use false for input errors such as null pointers or invalid values (row > height, etc.)
  • Use an enum to represent CHECKED, UNCHECKED, UNKNOWN etc. instead of a boolean. Many C libraries effectively do this by returning 0 (e.g. INVALID_SOCKET) to indicate an error (or sometimes -1).
  • Validate the inputs elsewhere to ensure that this function can always correctly return a meaningful boolean when called.
Related Topic