Is there a generic way to printf a variable? - c

If I have a macro like
#define MYMACRO(x) printf ("%any\n", x);
is there any %any formatter which can print anything, context-dependently?
Non-standard or GNU C specific are OK.

Update: Rewritten to focus more on the macro aspect.
If you limit yourself to a single argument, it's doable in C11 using generics. The linked-to page has an example, the gist of which is to use generics to map the type of the argument to the proper formatting string.
I don't want to "re-print" the entire blog post, but the macro begins:
#define printf_dec_format(x) _Generic((x), \
char: "%c", \
signed char: "%hhd", \
unsigned char: "%hhu", \
/* more code deleted */
#define print(x) printf(printf_dec_format(x), x)
#define printnl(x) printf(printf_dec_format(x), x), printf("\n");

If you want to print the value of a numeric expression, without wanting to tell the compiler if it's signed or unsigned (i.e. without %u flags etc.) or if it's long, long long or whatever...
...then there's a way that works with old C standards also (C99, C90, ...).
Just use the macro P99_SIGNED from the find P99 project -- it also works for old C standards.
#include <stdio.h>
#include <limits.h> /* CHAR_BIT, LLONG_MIN, etc. */
/* http://p99.gforge.inria.fr/p99-html/group__integers_ga3eb39ccac28ebd8265c1a31dc00f53ab.html
P99 homepage: http://p99.gforge.inria.fr/
P99 repo: https://scm.gforge.inria.fr/anonscm/gitweb?p=p99/p99.git;a=tree
*/
#define P99_SIGN_PROMOTE(A, B) (1 ? (A) : (B))
#define P99_PROMOTE_0(EXPR) P99_SIGN_PROMOTE(0, (EXPR))
#define P99_PROMOTE_M1(EXPR) P99_SIGN_PROMOTE(-1, (EXPR))
#define P99_SIGNED(EXPR) (P99_PROMOTE_M1(EXPR) < P99_PROMOTE_0(EXPR))
#define print_num(x) (P99_SIGNED(x) \
? printf("%lld", ( signed long long)(x)) \
: printf("%llu", (unsigned long long)(x)))
int main()
{
print_num(-1); /* prints -1 */
putchar('\n');
print_num(1); /* prints 1 */
putchar('\n');
print_num(LLONG_MIN); /* prints -9223372036854775808 (dependant on archi) */
putchar('\n');
print_num(ULLONG_MAX); /* prints 18446744073709551615 (dependant on archi) */
putchar('\n');
return 0;
}
This can also be a big help in understanding integer promotion rules, since using e.g. print_num(-1+0U) you'll see that the compiler promotes all operands to unsigned (you get a large positive value!)
As has been mentioned by others: If you have a compiler that can handle C11 or newer: use _Generic -> Link. under the heading Printing values generically.

Related

How to assert two types are equal in c?

How do I assert that two types are equal in C? In C++, I would use std::is_same, but searching StackOverflow and elsewhere seems only to give results for C++ and C#. Is there no way to do this in C?
Note, this is not asking whether a variable has a certain type but rather whether two types are the same.
How to assert two types are equal in c?
Use _Generic to get you at least mostly there with non-array types.
#define compare_types(T1, T2) _Generic(( (T1){0} ), \
T2: "Same", \
default: "Different" \
)
#include <stdio.h>
#include <stdint.h>
int main() {
// Same range
printf("%ld %lld\n", LONG_MAX, LLONG_MAX);
// Same size
printf("%zu %zu\n", sizeof (long), sizeof (long long));
// Yet different
printf("%s\n", compare_types(long, long long));
// int64_t is a long on my machine
printf("%s\n", compare_types(long, int64_t));
printf("%s\n", compare_types(long long, int64_t));
}
Output
9223372036854775807 9223372036854775807
8 8
Different
Same
Different
Improved
Further, a stronger compare employs a A vs B and B vs A test. The 2 tests are useful for the controlling expression of _Generic converts arrays to pointers of the first element losing some type information.
#define strong_helper(T1, T2) _Generic(( (T1){0} ), \
T2: 1, \
default: 0 \
)
#define compare_types_strong(T1, T2) (strong_helper(T1,T2) && strong_helper(T2,T1))
printf("%d\n", compare_types_strong(long, int64_t));
printf("%d\n", compare_types_strong(int [3], int *));
Output
1
0
Still troublesome for arrays and void
compare_types_strong(int [3], int [3]) returns 0 as _Generic converted the controlling expression int [3] to a pointer to the first element type (int *).
#PSkocik, in a deleted comment, points out this approach will not work for the incomplete object type void.
Under gcc, you could do something like this:
#define same_type(a, b) \
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), "types do not match")
...
int a, b;
float c;
same_type(a,b);
same_type(a,c);

Comparing C macros

I have addressing macros (it's on a microcontroller, so accessing physical address is OK) that break down to this (after a long sequence of conditional defines, attributes, etc):
#define ADDR_A (*18)
#define ADDR_B (*30)
#define ADDR_C (*18)
I would like to compare them so I can optimize the compilation:
#if ADDR_A==ADDR_C
return 1;
#else
return 0;
#endif
But I get "error: operator '*' has no left operand" which makes sense. Is it possible to compare the DEFINITIONS of macros. I have a hunch I could convert them to string somehow to compare, but I haven't found a way (like with the # for a macro argument).
And no, I'm not looking to do this at runtime as I'm counting the cycles.
You can't compare strings in an #if, because:
you can only use #if with constant expressions
strings can only be compared using a loop or a function
loops aren't constant expressions
and:
Constant expressions shall not contain assignment, increment, decrement, function-call,
or comma operators, except when they are contained within a subexpression that is not
evaluated. (C11, 6.6P3)
The best I can think of is to split up the addresses and the dereferencing into two different macros, like:
#define ADDR_A (18)
#define ADDR_B (30)
#define ADDR_C (18)
#define GET_A (*ADDR_A)
#define GET_B (*ADDR_B)
#define GET_C (*ADDR_C)
#if ADDR_A == ADDR_B
return 1
#else
return 0
#endif
Note that checking the equality of constants "at runtime" will be elided by pretty much any compiler worth its salt; in this example, the compiler just generates the equivalent of return 1 because it knows at compile-time that the condition will evaluate to false; counting cycles is a red herring here, because these comparisons will be elided.
Also, for what it's worth, I'm not sure how you're using those macros (I can't construct an example in my head where they would be syntactically valid), but I have a feeling your code would be easier to understand if you just made your macros contain the addresses and you dereference those addresses inline in your code. Were I reading your code, I would much prefer:
#define ADDR_A (18)
#define ADDR_B (30)
#define ADDR_C (18)
if (ADDR_A == ADDR_B)
return 1
return 0
How about putting only the addresses in the macros, and the type information separately?
#define ADDR_A (18)
#define ADDR_B (30)
#define ADDR_C (18)
unsigned uint16_t *A = (uint16_t*)ADDR_A;
unsigned uint16_t *B = (uint16_t*)ADDR_B;
unsigned uint16_t *C = (uint16_t*)ADDR_C;
Then you can use your tests.
Alternatively, skip the preprocessor, and just do it in C:
unsigned uint16_t *const A = (uint16_t*)18;
unsigned uint16_t *const B = (uint16_t*)30;
unsigned uint16_t *const C = (uint16_t*)18;
int f()
{
if (A == C)
return 1;
else
return 0;
}
Unless you have an extremely low-quality compiler, you can expect it to recognise A==C as a constant expression and simplify the code accordingly.

C macro that counts bits in odd positions for any data type

I need to write a macro that would count bits in odd positions (in ANSI C). For example, in 1010 the count of such bits is 2 while in 0101 the count is 0.
This is the macro I came up with:
#include <stdio.h>
#define BIT_IN_BYTE 8
#define size(x,t) { \
int i, sum = 0; \
for(i = 0; x; x >>= 1) { \
if( (x & 1) && (i % 2) != 0) { \
sum++; \
} \
i++; \
} \
t = sum; \
} \
int main() {
int b = 44444, result;
size(b, result);
printf("count = %d\n", result);
return 0;
}
I have 2 questions really: whether I could've written the macro in a way that it wouldn't need two arguments in its signature and more importantly if there's a relatively simple way to extend the macro onto float and double types.
As in the comments to your question, using a macro here really is not good practice. You should really use a function instead - inline or otherwise.
Since you're apparently forced to use a macro in your case for reasons outside of your control, here are some relevant points to your example:
You can use sizeof to get the number of bytes in whatever type you pass in your x parameter. This will potentially allow you to generalize the macros to different types (you mention float and double) that have different sizes.
Since the macro does not do type checking, if you have something that works for int in a generic way - probably using bit-wise operations - you'll have a fighting chance of making it work for other types. I again note, however, that the lack of type safety is a reason to avoid macros in many cases.
As noted in a comment on your question, your current approach destroys the value in whatever you pass as parameter x. That's likely undesired and unnecessary.
You would only be able to avoid passing the second parameter if you can rewrite this such that is evaluates to a number. I'm not motivated to figure out exactly how to do that for this contrived example or if it is actually possible.

Casting with #if in C

Why this code gives an error:
#include <stdio.h>
#define Rep (int)6
int main(){
#if Rep==6
printf("T");
#else
printf("F");
#endif
return 0;
}
Why does it refuse the casting?
Is it a 'preprocessor error' or a 'compiler error'?
This is a preprocessor error. It happens because the preprocessor does not understand how to cast a variable. You cannot use any C code with #if, just simple numbers, or macros which expand to a number.
If you cannot modify Rep, you can work around this with a helper macro, which removes the casting from the beginning:
#include <stdio.h>
#define X(x)
#define Y(x) X x
#define Rep (int)6
int main(void) {
#if Y(Rep) == 6
printf("%d\n", Y(Rep)); // prints 6
#endif
return 0;
}
Preprossor macros that combine casts and that still should work in #if are easy to write: you just add a little + before the number. In your case
#define Rep ((int)+6)
The preprocessor replaces identifiers that it doesn't know by 0 so the end result is the same value.
But also, the cast in your Rep macro by itself is quite useless. 6 is an int, anyhow. So better avoid a cast for all integer types that have their own literals, combinations of U and L as suffix should do in most cases.

Can the C preprocessor perform integer arithmetic?

As the questions says, is the C preprocessor able to do it?
E.g.:
#define PI 3.1416
#define OP PI/100
#define OP2 PI%100
Is there any way OP and/or OP2 get calculated in the preprocessing phase?
Integer arithmetic? Run the following program to find out:
#include "stdio.h"
int main() {
#if 1 + 1 == 2
printf("1+1==2\n");
#endif
#if 1 + 1 == 3
printf("1+1==3\n");
#endif
}
Answer is "yes", there is a way to make the preprocessor perform integer arithmetic, which is to use it in a preprocessor condition.
Note however that your examples are not integer arithmetic. I just checked, and gcc's preprocessor fails if you try to make it do float comparisons. I haven't checked whether the standard ever allows floating point arithmetic in the preprocessor.
Regular macro expansion does not evaluate integer expressions, it leaves it to the compiler, as can be seen by preprocessing (-E in gcc) the following:
#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
int i = ONEPLUSONE;
#endif
Result is int i = (1 + 1); (plus probably some stuff to indicate source file names and line numbers and such).
The code you wrote doesn't actually make the preprocessor do any calculation. A #define does simple text replacement, so with this defined:
#define PI 3.1416
#define OP PI/100
This code:
if (OP == x) { ... }
becomes
if (3.1416/100 == x) { ... }
and then it gets compiled. The compiler in turn may choose to take such an expression and calculate it at compile time and produce a code equivalent to this:
if (0.031416 == x) { ... }
But this is the compiler, not the preprocessor.
To answer your question, yes, the preprocessor CAN do some arithmetic. This can be seen when you write something like this:
#if (3.141/100 == 20)
printf("yo");
#elif (3+3 == 6)
printf("hey");
#endif
YES, I mean: it can do arithmetic :)
As demonstrated in 99 bottles of beer.
Yes, it can be done with the Boost Preprocessor. And it is compatible with pure C so you can use it in C programs with C only compilations. Your code involves floating point numbers though, so I think that needs to be done indirectly.
#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)
int div = HKB;
int rem = RKB;
This preprocesses to (check with gcc -S)
int div = 512;
int rem = 0;
Thanks to this thread.
Yes.
I can't believe that no one has yet linked to a certain obfuscated C contest winner. The guy implemented an ALU in the preprocessor via recursive includes. Here is the implementation, and here is something of an explanation.
Now, that said, you don't want to do what that guy did. It's fun and all, but look at the compile times in his hint file (not to mention the fact that the resulting code is unmaintainable). More commonly, people use the pre-processor strictly for text replacement, and evaluation of constant integer arithmetic happens either at compile time or run time.
As others noted however, you can do some arithmetic in #if statements.
Be carefull when doing arithmetic: add parenthesis.
#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8
If you ever use something like:
unsigned int i = TOTALSIZE/4;
and expect i to be 3, you would get 4 + 2 = 6 instead.
Add parenthesis:
#define TOTALSIZE (SIZE4 + SIZE8)

Resources