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.
Related
With reference to this question Quote macro for defining string, Idea is that I want to print the value of a macro constant, say for the following code:
#include<stdio.h>
#define X 4
#define Tostring(x) #x
main()
{
printf(Tostring(X));
}
It is printng X instead of 4, but with Quote macro for defining string I know how to correct it, but can someone explain what exactly is gong on here?
To print 4 as you wish you can one of these:
Stringizing the result:
#include<stdio.h>
#define Tostring(x) str(x)
#define str(x) #x
#define X 4
int main()
{
printf(Tostring(X));
}
or using function like macros to convert X to int:
#include<stdio.h>
#define X 4
#define Tostring(x)(X)
int main()
{
printf("%d\n", Tostring(X));
}
The first example is one of the examples that is given in documentation. There it is stated that two levels of macros shall be used if you want to stringize the result of the expansion of a macro. The result of the expansion is the following:
Tostring (X)
-> Tostring(4)
-> str (4)
-> "4"
In the second example you are relating the argument of Tostring macro with the X from the #define X 4 and thus you can print the value as an int.
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.
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.
I tried to run this code:
#define ROW_CNT 8;
#define COLUMN_CNT 24;
#define FIRST_COLUMN 2;
unsigned int volume[ROW_CNT][COLUMN_CNT][ROW_CNT];
but I get the following errors:
expected identifier or '(' before ']' token
Why is that?
Take off the semicolons on your #defines.
The #define directives are handled by the preprocessing stage of compilation, which is all about text substitution. So, whenever the preprocessor performs text substitution, your program becomes
unsigned int volume[8;][24;][2;];
which isn't valid C.
#define ROW_CNT 8;
#define COLUMN_CNT 24;
#define FIRST_COLUMN 2;
should be
#define ROW_CNT 8
#define COLUMN_CNT 24
#define FIRST_COLUMN 2
semicolons should not be used for #define
A pre-processor definition, such as ROW_CNT, replaces any instances of the identifier in your code with the value it's defined as being. Therefore once the pre-processor has expanded your macros, your code will look like:
unsigned int volume[8;][24;][2;];
As you can see, the semicolon is included after 8, 24 and 2, since that's how you defined ROW_CNT, COLUMN_COUNT and FIRST_COUNT to be, and that's obviously not valid C syntax.
Remove the semicolons from the end of your #defines and the code will compile.
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)