Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use functions that just return a constant instead of just using a constant?

I ran into some code on GitHub. https://github.com/codeplea/tinyexpr/blob/master/tinyexpr.c

These lines caught my eye:

static double pi(void) {return 3.14159265358979323846;}
static double e(void) {return 2.71828182845904523536;}

Is there any reason at all to use functions in this case? Why not use constants? You could use preprocessor macros, but that can make debugging harder. I have never seen this before. Is there any benefit of this?

like image 490
klutt Avatar asked Jan 26 '23 06:01

klutt


1 Answers

The main reason I can think of is to make it easier to search for where that constant is used. For example, you search for e( instead of e.

That isn't the case here, however. The functions are being used, but not called explicitly.

The linked code contains an array of structs:

typedef struct te_variable {
    const char *name;
    const void *address;
    int type;
    void *context;
} te_variable;

...

static const te_variable functions[] = {
    /* must be in alphabetical order */
    {"abs", fabs,     TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"acos", acos,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"asin", asin,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"atan", atan,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"atan2", atan2,  TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"ceil", ceil,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"cos", cos,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"cosh", cosh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"e", e,          TE_FUNCTION0 | TE_FLAG_PURE, 0},
    {"exp", exp,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"fac", fac,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"floor", floor,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"ln", log,       TE_FUNCTION1 | TE_FLAG_PURE, 0},
#ifdef TE_NAT_LOG
    {"log", log,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
#else
    {"log", log10,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
#endif
    {"log10", log10,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"ncr", ncr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"npr", npr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"pi", pi,        TE_FUNCTION0 | TE_FLAG_PURE, 0},
    {"pow", pow,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"sin", sin,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"sinh", sinh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"sqrt", sqrt,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"tan", tan,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"tanh", tanh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {0, 0, 0, 0}
};

The second member of each struct is a function pointer used to run some math related function, and the values of E and PI are among them. So it looks like they were defined as functions to conform to this framework.

like image 177
dbush Avatar answered Feb 15 '23 22:02

dbush