-1

Which is better for code readability and further documentation of the code? Define return values and return function like this?

#define RETURN_OK       0
#define RETURN_NOT_OK   -1

int do_it(void)
{
    /*...*/
    return RETURN_OK;
}

or create separate enum?

typedef enum
{
    RETURN_NOT_OK = -1,
    RETURN_OK = 0
} RET_VAL;

RET_VAL do_it(void)
{
    /*...*/
    return RETURN_OK;
}
user3742046
  • 171
  • 12
  • This is very much debatable and opinion based, which is off topic here, but generally being more specific about things (the latter) is always better. – Sami Kuhmonen Sep 27 '21 at 08:19
  • If the `enum` is not long enough, I'd normally prefer the `#define` style. So, for this particular example, I'd prefer `#define` version. Also, the `RET_VAL` name is awkward. Having said that, these type of things are all subjective. Choose your own style. – Fractal Sep 27 '21 at 08:24
  • 1
    I like enums as debuggers convert numerical values the symbols which makes debugging much easier – 0___________ Sep 27 '21 at 08:27
  • @cornuz who did tell you that? https://godbolt.org/z/Ghaq8b6G3 – 0___________ Sep 27 '21 at 08:29
  • @cornuz delete the misleading comment then – 0___________ Sep 27 '21 at 08:41

4 Answers4

1

Which is better for code readability and further documentation of the code?

Is very subjective. It strongly depends on developers personal taste and preference, specific use case, project code guidelines.

When comparing the two presented versions, the second version is better, as the function declaration serves as a documentation that the return value of do_it is one of RET_VAL enumerations.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
1

Well #define and enum both are diff,(though in your case the diff is irrelevant).

But I would prefer enum as they can be used as datatype too.

Example

void doSomething(RET_VAL result)
{...}

{
   RET_VAL choice = RETURN_OK
   switch(choice) {
    case RETURN_OK: break;
    case RETURN_NOT_OK: break;

}
}

This makes the code more readable

Abhinav Singh
  • 302
  • 3
  • 15
1

C has pretty much non-existent type safety for integers and enums, so you won't get any better type safety from using the enum. It doesn't exactly help that enumeration constants (these: RETURN_OK) are actually defined to be of type int and not of the enum type as would make more sense.

Though as mentioned in the question of How to create type safe enums? you can also get ever so slightly better type safety in case you use pointers instead of pass-by-value.

Static analysers may be able to find type-related bugs in case you use an enum type - but that only matters in case you actually use static analysers. For example MISRA-C uses a system where enums are to be regarded and treated as if they were a type of their own, so a MISRA checker would give errors when using raw integer values instead of enumeration constants etc.

But what it boils down to in the end is de facto coding standards in C code bases. It is a very common API design to reserve the return value of all functions in a library for error codes, and then that error code is typically given a type of its own, often in the form of an enum. So I would go with the enum version because that's what most people out there are using, no matter if coding for *nix, Windows or embedded systems.

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

I think in general it is better style to use an enum since you are documenting your intent that your function returns a limited set of things (even though the compiler may not actually check this, which can be a disadvantage); but as pointed out in one of the comments, many compilers will give hints with enums, and will return the enum string when debugging rather than the cryptic number value.

Enums have other advantages when used as compile time constants when initializing static scoped structure variables.

bd2357
  • 704
  • 9
  • 17