Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C way to indicate failure in function

Tags:

c

I have a range of C functions:

const char* find_string(uint8_t id);
int32_t find_int32(uint8_t id);
uint32_t find_uint32(uint8_t id);
uint64_t find_uint64(uint8_t id);

Which return the found item (in a linked list). For string I can return a null string. But for the integer values I want to indicate whether the integral value was found or not. What is the C idiom way to do this?

Like this: ?

uint32_t find_uint32(uint8_t id, int* success);
like image 575
Angus Comber Avatar asked Nov 29 '25 04:11

Angus Comber


2 Answers

There's no one way to accomplish this, but the typical solution is this:

int find_uint32(uint8_t id, uint32_t *result)

Letting the function return a status code rather than the result. The actual result is "returned" through a pointer. While opinions differ here, it might be a good idea to have the function return zero on failure, so that you can do things like:

if (!find_uint32(42, &out)) {
    /* error */
}

One reason to have it the other way around, i.e., return the status code through a pointer parameter and the result as the function's return value, is that you could allow passing NULL to the status code if errors are to be ignored. That way, if you for some reason need not worry about errors, your code will be more readable; consider:

uint32_t val = find_uint32(42, NULL /* don't care */);

In some cases you can reserve a "magic value" as an error indicator. As you mentioned, the NULL pointer works for strings. If you are sure that some integer value is never a valid result, you could let it indicate error. For instance, if you have a function that returns unsigned values that will never exceed 0x7FFFFFFF, you could let the 31st bit indicate error, leaving the remaining 31 bits to carry data or an error code depending on the value of the top bit.

I would generally discourage this practice, the rationale being that magic error numbers will make the code harder to read and maintain than explicitly returning an error flag.

like image 79
Martin Törnwall Avatar answered Dec 01 '25 17:12

Martin Törnwall


What about:

int find_uint32(uint8_t id, uint32_t *val);

You pass a pointer to the result and return 0 for success and != 0 for error.

If you like the convenience of using find_uint32 in an expression, you can also return a pointer to the element (or in a linked list to the node). You'll need to dereference the pointer to access the value but you can then also use NULL in the result pointer to indicate an error:

uint32_t *find_uint32(uint8_t id);
like image 23
ouah Avatar answered Dec 01 '25 17:12

ouah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!