Jump to content

macros problem........ help please........

- - - - -

  • Please log in to reply
11 replies to this topic

#1
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
the first code snippet is

#include<stdio.h>
#define dprint(x) printf(#x " =%f\n",(float)x)
int main(void){
int j,x=4,y=2;
dprint(x/y);
j=(x/y);
printf("%f\n",j);
printf("%f\n",x/y);
}
the result is a few warnings on compiling and the following output

x/y =2.000000
2.000000
2.000000
when i remove (float) from the macros definition like below

#include<stdio.h>
#define dprint(x) printf(#x " =%f\n",x)
int main(void){
int j,x=4,y=2;
dprint(x/y);
j=(x/y);
printf("%f\n",j);
printf("%f\n",x/y);
}
the result of executing this new code is a few warnings on compiling and the following output

x/y =0.000000
0.000000
0.000000
how is the macros definition affecting the rest of the program??

any insight appreciated....

#2
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
Were you expecting the last example to output 2.00?

When the macro divides the integer 2 by the integer 4 and returns an integer.. the result is 0. so the code worked flawlessly.

int x = 2/4;
// x = 0

int x = 2 % 4;
// x = 2

The great thing about macros functions are that they are basically in-line functions.

More in-line than you might like though..

when you have this line:

dprint(x/y);

it is expanded to
printf("x/y" " =%f\n",x/y)

Before!!! the compiler starts converting code into object code.

#define is the preprocessor, so the preprocessor hits the dprint(x/y); line before the compiler does.

so now looking back at this:
printf("x/y" " =%f\n",x/y)

x/y is 0
printf outputs 0 to the terminal just as it was told to.

when you put

j = x/y


j has the value of 0

remember how the division operator works on integers vs how it works on floats.

Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!


#3
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
but i didn't do 2/4 anywhere. i have done x/y in both codes where x=4 and y=2. so where is 2/4 coming from?

#4
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
I'm sorry, too tired gotta get to bed soon lol.

Let me play with the code for a sec. gimi a min.

Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!


#5
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
Ok figured out the problem.

printf uses a va list in it's parameter list.

(this is how you can use any amount of arguments you want to)

when the va list is used there are no types with the data.. just data.

so this is what happened with your function.

printf() was sent the integer equivalent of 2.. which is 0x0002 in hex as the only argument in the va list.
the va list, having no explicit data types on it's elements was told to treat the first element as a float when you used the %f in the string.

printf now used the value 0x0002 to display a float. and I guess in whatever way x86 processors represent floats, 0x0002 means 0.

when you had float in the declaration, it worked because the compiler was told to convert the integer into a float before it displayed the results.

In the second version without float in the declaration, the int was never converted to a float, it was just assumed to be a float.

Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!


#6
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
so if having (float) in the macro definition was the reason of dprint(x) printing 2.00 then why is this affecting the other printf() statements. the other two printf() statements should continue to print whatever value they were printing even after the (float) was removed from the macro definition in the second code. how is the macro definition affecting the rest of the program?

#7
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
help :crying:

#8
Xupicor

Xupicor

    Learning Programmer

  • Members
  • PipPipPip
  • 46 posts
Short answer would be - avoid macros if you can.

If you use gcc - you can run it with -E flag to get your code after preprocessor took care of it. Usually you want to get rid of #include parts, because you will get all the headers in one output file ;)
$ gcc -std=c99 -E kod.c

# 1 "kod.c"

# 1 "<built-in>"

# 1 "<command-line>"

# 1 "kod.c"


int main(void) {

    int j, x = 3, y = 2;

    printf("x / y" " =%f\n",((float)x / y)); 

    j = (x / y);

    printf("%f\n", j);

    printf("%f\n", x / y);


    return 0;

}
Heck if I know why it affects printf that way.
Also, compiled without the <stdio.h> header:
$ gcc -ansi -pedantic -Wall -Wextra -std=c99 kod.c && ./a.exe

kod.c: In function 'main':

kod.c:7:5: warning: implicit declaration of function 'printf'

kod.c:7:5: warning: incompatible implicit declaration of built-in function 'prin

tf'

kod.c:9:5: warning: format '%f' expects type 'double', but argument 2 has type '

int'

kod.c:10:5: warning: format '%f' expects type 'double', but argument 2 has type

'int'

x / y =1.500000

1.500000

1.500000
And with it:
$ gcc -ansi -pedantic -Wall -Wextra -std=c99 kod.c && ./a.exe

x / y =1.500000

1.500000

1.500000
Pretty strange if you ask me. I wouldn't bother tinkering with the macro more than I'd have to, so, my solution that still gives you the debug output of variable names using a macro AND a function, is as follows:

#include <stdio.h>


void dprint(float f, const char* msg) {

    printf("%s = %f\n", msg, f);

}


#define dprint(x) dprint(((float)x), #x)


int main(void) {

    int j, x = 3, y = 2;

    dprint(x / y);

    j = (x / y);

    

    dprint(j);

    printf("%f\n", j);

    

    printf("%f\n", (float)x / y);

    

    return 0;

}
And it runs much better, if you ask me:

$ gcc -ansi -pedantic -Wall -Wextra -std=c99 kod.c && ./a.exe

x / y = 1.500000

j = 1.000000

nan

1.500000

About inlining C functions: Inline Functions In C

#9
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
You know I'm really not sure, however passing an int into a function that expects a double is problematic anyways.

check out the printout of this code:
printf( "%d, %d\n", sizeof(double), sizeof(int) );

prints:
8, 4

you pass 4 bytes (integer) in to a function that expects 8 bytes.

Maybe there doesn't have to be a reason why printf works when you put float one time and not the rest.

Passing 4 bytes into a function that expects 8 bytes results in undefined behavior. Thats enough to stop right there.
Obviously from the code you are analyzing, you found out that printf doesn't work properly at all after you corrupt it once.

Maybe printf has built in cache... who knows?

Is this a homework assignment or are you curious? I'm sure if you spent some time reading up on how printf and va lists work you could find your answer.

edit:
After a few minutes of reading and googling rather than just trying to come up with an answer I found the answer:
why the printf is not typecasting the int to float - C / C++ answers
Does printf() depend on order of format specifiers? - efreedom
c++ - Difference between float and double - Stack Overflow

Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!


#10
Xupicor

Xupicor

    Learning Programmer

  • Members
  • PipPipPip
  • 46 posts
My answer didn't get trough yesterday, as it seems... Well, long story short: avoid macros if you can.
But, if you still want a working solution:
#include <stdio.h>


void dprint(float f, const char* msg) {

    printf("%s = %f\n", msg, f);

}


#define dprint(x) dprint(((float)x), #x)


int main(void) {

    int j, x = 3, y = 2;

    dprint(x / y);

    j = (x / y);

    

    dprint(j);

    printf("%f\n", j);

    

    printf("%f\n", (float)x / y);

    

    return 0;

}
$ gcc -ansi -pedantic -Wall -Wextra test.c && ./a.exe

x / y = 1.500000

j = 1.000000

nan

1.500000
About inlining functions: Inline Functions In C

edit: Ah, sorry, it seems that my answer was waiting for a moderator to accept it. Sorry for duplicating it. :)

Edited by Xupicor, 21 January 2011 - 05:27 PM.


#11
sam_l

sam_l

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
Do not use macro's for things like that. Why you ask, well Stroustrup himself has something to say on the matter.

Stroustrup: C++ Style and Technique FAQ

#12
Skippy

Skippy

    Programmer

  • Members
  • PipPipPipPip
  • 146 posts
Xupicor is right. With the function version, the function is expecting a float, so when you pass the int to it, the int will be implicitly converted to a float before printf gets a hold of the value. This method will work.

Interested in participating in community events?
Want to harness your programming skill and turn it into absolute prowess?
Come join our programming events!





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users