Efficient way to handle identical functions, but with different operators in C

Say, in C, I have 2 methods that are completely identical, but 1 adds a value, and the other produces it:

void decreaseValue(handle* myData, uint8_t amount)
{
    /* Stuff going on */
    myData->someAttribute -= amount;
    /* Stuff going on */
}

void increaseValue(handle* myData, uint8_t amount)
{
    /* Stuff going on */
    myData->someAttribute += amount;
    /* Stuff going on */
}

With the exception of operators, both functions are completely identical, resulting in quite a few lines of duplicated code, which is not trivial.

Is there a safe, portable, not ugly way to handle this, or am I stuck in ctrl + c ctrl + v?

Switch Flag Potential:

typedef enum
{
    ADD,
    SUBSTRACT
}operator;

void modifyValue(handle* myData, uint8_t amount, operator op)
{
    /* Stuff going on */
    switch(op){
    case ADD: 
        myData->someAttribute += amount;
        break;
    case SUBSTRACT:
        myData->someAttribute -= amount;
        break;
    /* Stuff going on */
}

It works, but does not feel better.

+4
source share
6 answers

How about this:

static inline void changeValue(handle* myData, int amount)
{
    /* Stuff going on */
    myData->someAttribute += amount;
    /* Stuff going on */
}

void increaseValue(handle* myData, uint8_t amount)
{
    changeValue(myData, (int)amount);
}

void decreaseValue(handle* myData, uint8_t amount)
{
    changeValue(myData, -(int)amount);
}
+5
source

Using a preprocessor:

#define modifyValue(name, operator)                  \
    void name##Value(handle* myData, uint8_t amount) \
    {                                                \
        /* Stuff going on */                         \
        myData->someAttribute operator= amount;      \
        /* Stuff going on */                         \
    }

modifyValue(increase, +)
modifyValue(decrease, -)
+1
source

enum?

typedef enum
{
    SUBTRACT,
    ADD,
    ...
} enumOperator;

void modifyValue(handle* myData, uint8_t amount, enumOperator operator)
{
    switch(operator)
    {
        case SUBTRACT:
            myData->someAttribute -= amount;
            break;
        case ADD:
            myData->someAttribute += amount;
            break;
        case ...:
            ...;
            break;
    }
}
+1

void addAmount(handle* myData, uint8_t amount)
{
    myData->someAttribute += amount;    
}

void subtractAmount(handle* myData, uint8_t amount)
{
    myData->someAttribute -= amount;    
}

Create a genericFunction that can take one of the above functions as an argument.

void genericFunction(handle* myData, uint8_t amount,
                     void (*fun)(handle*, uint8_t))
{
    /* Stuff going on */

    /* Call the function */
    fun(myData, amount);

    /* Stuff going on */
}

Call genericFunctionwith addAmountorsubtractAmount

genericFunction(mData, amount, addAmount);
0
source

If your method is small enough, it is best not to call an unnecessary function. Use an if-else or switch.

0
source
void doStuff(handle* myData, uint8_t amount, void (*func)(handle*, uint8_t))
{
    /* Stuff going on */
    func(myData, amount);
    /* Stuff going on */
}

Then use it as follows:

void decrease(handle* myData, uint8_t amount) { myData->someAttribute -= amount; }
void increase(handle* myData, uint8_t amount) { myData->someAttribute += amount; }

void decreaseValue(handle* myData, uint8_t amount)
{
    doStuff(myData, amount, decrease);
}
void increaseValue(handle* myData, uint8_t amount)
{
    doStuff(myData, amount, increase);
}

Basically you use the delegate equivalent (or lambdas) in C. doStuffdoes the actual things that will be duplicated.

-1
source

All Articles