What is the problem with this preprocessor in the code below? - c

//C code starts
#define mod(a) (a>=0?a:-a)
#include<stdio.h>
int main(){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
printf("%d %d %d %d %d\n",x,y,z,y-z,x-z);
if(mod(y-x)<mod(x-z)) printf("%d %d Cat A",mod(y-z),mod(x-z));
else if(mod(y-z)>mod(x-z)) printf("%d %d Cat B",mod(y-z),mod(x-z));
else printf("Mouse C");
printf("\n");
}
/*code ends here*/
For the input of "1 3 2" I would expect the output to be "Mouse C" but it is not the case.
Also if we add all the variables in mod in one more bracket (e.g. if the mod(y-z) is then written as mod((y-z)) ) then the output comes as expected.
So why it is going on?

Macros perform direct text (or more accurately, token) substitution. So this:
mod(y-x)
Is exactly the same as this:
(y-x>=0?y-x:-y-x)
Notice that the last part is -y-x, i.e. the negation of y minus x, while what you wanted was -(y-x). This is a prime example of why macro arguments should always be placed in parenthesis as follows:
#define mod(a) ((a)>=0?(a):-(a))
When you want to see what your macro actually does, look at your code after the preprocessor has actually done its job:
gcc -E file.c
clang -E file.c or clang --preprocess file.c
cl.exe /E file.c, cl.exe /P file.c, or cl.exe /EP file.c for those on windows

It's in general a bad idea to use macros for these things. Use a function instead.
First thing is that you the preprocessor just replaces text. mod(y-x) will be expanded to (y-x>=0?y-x:-y-x) which is obviously wrong. You can remedy this with
#define mod(a) ((a)>=0?(a):-(a))
But here's another catch. Suppose you do this:
mod(f())
where f is a function with side effects. For instance the rand() function. The macro would then make three function calls.
You can solve this problem in gcc (thus making it non-portable) with this construct:
#define mod(a) ({ int _a=a; _a>=0?_a:-_a; })
But isn't it easier to just do this?
long long mod(a) {
return a>=0?a:-a;
}

Related

How can I get all modulo(%) operation in my C source code

How can I get all modulo(%) operation in my c source code?
I don't think a regular expression can do it, due to C MACRO inclusion.
And, must take care of string printf formatting.
Which static analyse source code can I use to do this?
For exemple, Codesonar or codecheck "only" try find problems, not that.
I want to check manually all modulo operation with zero. (like division by 0).
It's probably not the best way to do this, but it seems to work. Here's my test file:
#include <stdio.h>
#define MACRO %
int main(void) {
int a = 1%1;
int b = 1 MACRO 1;
printf("%1s", "hello");
}
Then I ran this and got some useful output:
$ clang -fsyntax-only -Xclang -dump-tokens main.c 2>&1 > /dev/null | grep percent
percent '%' Loc=<main.c:6:14>
percent '%' [LeadingSpace] Loc=<main.c:7:15 <Spelling=main.c:3:15>>
Short explanation:
This is the output from the lexical analysis. The command seem to write to stderr instead of stdout. That's the reason for 2>&1 > /dev/null. After that I'm just using grep to find all occurrences of the modulo operator.

C code after preprocessor

This is an exercise taken by a book. The question is what is the output of this code.
This code prints always "N is undefined", but I don't know why. The command "#undef N" is after the function f. Then, why the output is always "N is undefined"?
#define N 100
void f(void);
int main(void)
{
f();
#ifdef N
#undef N
#endif
return 0;
}
void f(void)
{
#if defined(N)
printf("N is %d\n", N);
#else
printf("N is undefined\n");
#endif
}
The point of this exercise is to demonstrate that preprocessor's control flow is completely separate from the control flow of your program.
#if/#undef directives are processed in the order that they appear in the text of your program. They are processed only once at compile time; the decision to define or undefine a preprocessor variable cannot be reconsidered at runtime.
That's why the fact that f executes before #if/#undef line of the main is irrelevant. You can change the output of this program only by moving f to a position in file before main.
If you run the compiler with the -E flag (for gcc at least) it'll show you what the code you're actually compiling is.
You'll see that the preprocessor doesn't follow the code execution - it performs its actions in the order that they appear in the file.
Then the compiler takes the resulting code and f just has the one call to printf in it that says N isn't defined.
The C preprocessor goes through your code line by line. As such, it is wrong to assume the #undef happens after the function f() because of the function call. Instead, it happens before your definition of function f().
To understand this, you have to distinguish between the preprocessor (line by line) and the control flow (follows function calls).
Because the preprocessors instructions run in the "physycal" order, line after line.
Think about it something is executed before actual compilation, in a such way your code be clear, only with plain C code for the compiler.

Expanding a dynamic macro inside printf function

I want to compile a c program under different names. In the main file, I have the following macro:
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME "defaultname"
#endif
When compiling using gcc, I use -D switch to define this macro (is that the right term?):
$ gcc main.c -DEXECUTABLE_NAME="newname"
I do not know if the -D works fine or not because when I try to do something like the code below...it fails...I can not tell if the -D switch is screwing up or the syntax of using the macro inside the printf() function is not correct:
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
I get this error:
main.c:48:57: note: in expansion of macro ‘EXECUTABLE_NAME’
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
Any suggestions?
It works, and you can see that because of the error. Which by the way is because you're defining your macro wrong on the command line, this is how you quote a string in a macro:
$ gcc main.c -DEXECUTABLE_NAME='"newname"'
And this said, it's not even needed. The executable path is always your first argument: *argv.
I tried this program with an integer, which is as follows
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME 2
#endif
int main()
{
printf("%d",EXECUTABLE_NAME);
}
and then typed gcc main.c -DEXECUTABLE_NAME=1 and it works as the value changes to 1. Is it a problem with the data type 'string' that you are using?

Is math within macro computed at compile time?

For example, does MIN_N_THINGIES below compile to 2? Or will I recompute the division every time I use the macro in code (e.g. recomputing the end condition of a for loop each iteration).
#define MAX_N_THINGIES (10)
#define MIN_N_THINGIES ((MAX_N_THINGIES) / 5)
uint8_t i;
for (i = 0; i < MIN_N_THINGIES; i++) {
printf("hi");
}
This question stems from the fact that I'm still learning about the build process. Thanks!
If you pass -E to gcc it will show what the preprocessor stage outputted.
gcc -E test.c | tail -n11
Outputs:
# 3 "test.c" 2
int main() {
uint8_t i;
for (i = 0; i < ((10) / 5); i++) {
printf("hi");
}
return 0;
}
Then if you pass -s flag to gcc you will see that the division was optimized out. If you also pass the -o flag you can set the output files and diff them to see that they generated the same code.
gcc -S test.c -o test-with-div.s
edit test.c to make MIN_N_THINGIES equal a const 2
gcc -S test.c -o test-constant.s
diff test-with-div.s test-constant.s
// for educational purposes you should look at the .s files generated.
Then as mentioned in another comment you can change the optimization flag by using -O...
gcc -S test.c -O2 -o test-unroll-loop.s
Will unroll the for loop even such that there isn't even a loop.
Preprocessor will replace MIN_N_THINGIES with ((10)/5), then it is up to the compiler to optimize ( or not ) the expression.
Maybe. The standard does not mandate that it is or it is not. On most compilers it will do after passing optimization flags (for example gcc with -O0 does not do it while with -O2 it even unrolls the loop).
Modern compilers perform even much more complicated techniques (vectorization, loop skewing, blocking ...). However unless you really care about performance, for ex. you program HPC, program real time system etc., you probably should not care about the output of the compiler - unless you're just interested (and yes - compilers can be a fascinating subject).
No. The preprocessor does not calculate macros, they're handled by the compiler. The preprocessor can calculate arithmetic expressions (no floating point values) in #if conditionals though.
Macros are simply text substitutions.
Note that the expanded macros can still be calculated and optimized by the compiler, it's just that it's not done by the preprocessor.
The standard mandates that some expressions are evaluated at compile time. But note that the preprocessor does just text splicing (well, almost) when the macro is called, so if you do:
#define A(x) ((x) / (S))
#define S 5
A(10) /* Gives ((10) / (5)) == 2 */
#undef S
#define S 2
A(20) /* Gives ((20) / (2)) == 10 */
The parenteses are to avoid idiocies like:
#define square(x) x * x
square(a + b) /* Gets you a + b * a + b, not the expected square */
After preprocessing, the result is passed to the compiler proper, which does (most of) the computation in the source that the standard requests. Most compilers will do a lot of constant folding, i.e., computing (sub)expressions made of known constants, as this is simple to do.
To see the expansions, it is useful to write a *.c file of a few lines, just with the macros to check, and run it just through the preprocessor (typically someting like cc -E file.c) and check the output.

printf doesn't work, even with newline and fflush()

I'm compiling the below C code with gcc. No errors are thrown during compilation or at runtime. I ran through the code with gdb, and the answer given in sum is correct at the end, yet the printf() does not display anything on the screen. I've tried all sorts of combinations of fprintf(), printf(), and fflush(), but nothing works.
What do I need to change so the program will print the result to stdout?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 9;
int i, sum; i = 1, sum = 0;
while (i < 2 * num) {
sum = sum + i * i;
++i;
}
printf("sum: %d\n", sum);
fflush(stdout);
return 0;
}
The code is correct, and should print sum: 1785 for any conforming implementation.
This is a guess (update: which turns out to be correct), but ...
You've named the source file test.c, and you compile it with:
$ gcc test.c -o test
(or something similar) and execute it with:
$ test
which produces no output.
The problem is that test is a standard Unix command (and also a built-in command in some shells). When you type a command name to the shell, it first looks for built-in commands, then for executables in directories specified in your $PATH environment variable.
To execute a command in the current directory, prepend ./ to the name:
$ ./test
sum: 1785
$
This applies to any command in the current directory. There are so many built-in commands that you can't reasonably avoid colliding with them. Cultivating the habit of running executables in the current directory by typing ./whatever means that name collisions don't matter.
(Don't be tempted to add . to the front of your $PATH; that's dangerous. Think about what could happen if you cd into a directory and type ls, if there happens to be a malicious ls command there.)
There is nothing wrong with your program. It has to work. Try running it with redirection:
./a.out > myout
..and see if you get any output. If not, I'd suspect there is a problem with some kind of standard library mismatch.
Another option to check would be to build using SUN C compiler as opposed to gcc and see if that works. If it does, gcc is the culprit.

Resources