Reputation: 431
I have put in my code a
typedef int myinteger ;
I want however all my code to continue to be valid if I change the typedef to another integer type.
Now I want to printf a variable of type myinteger
. Is it a way to do it properly? I have just found the following "hack":
printf("%lld", myvariable) ;
hoping that any integer type will fit in a long long
and that the compiler will do the proper conversion. It seems to works with gcc (although I have a warning). printf
is a problem but they can be other problems too (like finding the maximum "myinteger").
More generally is it possible/desirable to try what I try to achieve, writing code assuming only that myinteger
refers to some integer type?
Upvotes: 2
Views: 800
Reputation: 154242
If all code needs to do is print the integer, and using C99 or C11, use _Generic
to select the matching print specifier.
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#define IntegerFormat3(X) _Generic((X), \
size_t: "%zu", \
ptrdiff_t: "%td", \
default: 0 \
)
#define IntegerFormat2(X) _Generic((X), \
intmax_t: "%jd", \
uintmax_t: "%ju", \
default: IntegerFormat3(X) \
)
#define IntegerFormat(X) _Generic(X, \
_Bool: "%d", \
char: "%c", \
signed char: "%hhd", \
unsigned char: "%hhu", \
short: "%hd", \
unsigned short: "%hu", \
int: "%d", \
unsigned: "%u", \
long: "%ld", \
unsigned long: "%lu", \
long long: "%lld", \
unsigned long long: "%llu", \
default: IntegerFormat2(X) \
)
int main(void) {
int i = 12;
unsigned long long u = 34;
size_t sz = 56;
printf(IntegerFormat(i), i);
printf(IntegerFormat(u), u);
printf(IntegerFormat(sz), sz);
return 0;
}
Unfortunately printf(IntegerFormat(i) "\n", i);
does not work.
Another C approach to formatted printing without any coded type dependent specifiers Formatted print without the need to specify type matching specifiers using _Generic.
Still, casting to the widest matching sign-ness type is simple as answered by others.
Upvotes: 0
Reputation: 15642
Consider branching depending on whether the value is negative, and casting to the intmax_t
and uintmax_t
types; there's no guarantee that long long int
or unsigned long long int
be the largest integer types, yet these max
types are guaranteed to be the largest.
For example:
#include <inttypes.h>
/* ... */
if (my_variable < 0) printf("%jd", (intmax_t) my_variable);
else printf("%ju", (uintmax_t) my_variable);
Upvotes: 1
Reputation: 1736
I recommend:
typedef int my_type_t;
#define FMT_MY_TYPE "%d"
Then:
my_type_t my_var = 0;
printf("Here is my_var: " FMT_MY_TYPE "\n", my_var);
This even works with structs. Here is a generalization:
typedef struct { int a; int b; } my_struct_t;
#define FMT_MY_STRUCT "{a: %d, b: %d}"
#define FMT_MY_STRUCT_ARG(x) (x).a, (x).b
Then:
my_struct_t my_var = {0, 1};
printf("Here is my_var: " FMT_MY_STRUCT "\n", FMT_MY_STRUCT_ARG(my_var));
Upvotes: 5
Reputation: 121427
There's no universal format specifier that can be used in printf()
to print any integer type. One way is to cast to C99's intmax_t
or uintmax_t
and print it:
#include <stdint.h>
printf("%jd\n", (intmax_t)myvariable);
printf("%ju\n", (uintmax_t)myvariable);
This will work for all integer types as intmax_t
/uintmax_t
is the type maximum width integer.
In general, arbitrarily changing the typedef
suggests there's a fundamental flaw in the design.
Upvotes: 5
Reputation: 145899
It seems to works with gcc (although I have a warning).
You need to add a cast.
printf("%lld", (long long) myvariable);
More generally is it possible/desirable to try what I try to achieve, writing code assuming only that "myinteger" refer to some integer type?
The "generic" printf
call is a bad design smell. Moreover, what if myvariable
is of type unsigned long long
and its value is greater than LLONG_MAX
?
Upvotes: 1
Reputation: 122458
You'd have to cast to long long
in the call to printf()
as it's the longest integer type:
printf("%lld", (long long)myvariable);
Upvotes: 1