I have a decimal to octal conversion function, and would like to call it with either an int or an unsigned int depending on some options. My first thought was to copy/paste the code and just change the parameter's type ... is there a better way ?
2 Answers
You can use unions:
#include <stdio.h>
enum octal_type {AS_INT, AS_UINT};
typedef union {
int as_int;
unsigned as_uint;
} t_octal;
void fn(t_octal value, enum octal_type type)
{
switch (type) {
case AS_INT:
printf("%d\n", value.as_int);
break;
case AS_UINT:
printf("%u\n", value.as_uint);
break;
}
}
int main(void)
{
t_octal value;
value.as_int = 5;
fn(value, AS_INT);
return 0;
}
Or generic pointers:
#include <stdio.h>
enum octal_type {AS_INT, AS_UINT};
void fn(const void *value, enum octal_type type)
{
switch (type) {
case AS_INT:
printf("%d\n", *(int *)value);
break;
case AS_UINT:
printf("%u\n", *(unsigned *)value);
break;
}
}
int main(void)
{
int value = 5;
fn(&value, AS_INT);
return 0;
}
Under C11 you can ommit the second parameter in the call using _Generic
:
#include <stdio.h>
enum octal_type {AS_INT, AS_UINT};
#define fn(x) fn_impl(x, \
_Generic(*x, signed int: AS_INT, unsigned int: AS_UINT, default: AS_INT))
void fn_impl(const void *value, enum octal_type type)
{
switch (type) {
case AS_INT:
printf("%d\n", *(int *)value);
break;
case AS_UINT:
printf("%u\n", *(unsigned *)value);
break;
}
}
int main(void)
{
int value = 5;
fn(&value);
return 0;
}

- 39,972
- 7
- 52
- 94
Well, if you need to do overloading in C you have three choices.
- Implement VFT your self. There are many ways of creating a VFT and calling the appropriate function depending on what you want to do. Just do a check for OO in C
- Use the preprocessor. You can use type agnostic procedures in the preprocessor. But you will have to do many checks for the type of arguments or apply procedures that are also type agnostic.
- Use an argument to provide you with the case. You can have a wrapper function with three arguments; the main two arguments, possibly of type void pointers, and one of type string, enum, type defined in the preprocessor or other of similar behavior. Depending of the latter, you will do typecasts and call the appropriate function your self.
Or... you could use a struct/union (in an object like fashion) and depending on the characteristics of it to do the appropriate calculations. But I think that for what you have to do this last approach would be more that too much effort. Actually, all would be too much effort. What I would do, would be to have one function with void pointer as first argument, a pointer to the output and a third argument defining the type of the first argument. The process is the same but you have different limits that can cause overflow in extreme or negative values. Thus, by the third argument you would typecast the first void pointer and do the conversion.

- 1,784
- 1
- 15
- 24
-
How are you supposed to know if an integer is signed or unsigned by checking its value? :) You don't know if it's signed or unsigned so you don't know how to interpret the value. "Above the limits of signed int" is the same thing as "if it's negative". (With two's complement that is atleast.) – Jite Feb 28 '15 at 10:36
-
Yes, @Jite. You are correct. Actually I did the edit before I see your comment. – Xxxo Feb 28 '15 at 10:37
-