LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-20-2009, 11:27 AM   #1
man s
LQ Newbie
 
Registered: Dec 2009
Posts: 14

Rep: Reputation: 0
C preprocessor??Plz Help!!


Hello folks!
I have recently encountered a snippet of C preprocessor code which has been troubling me since the past few days.
Here it is:

#define SQR(x) (x*x)
main(){

int a,b=3;
a=SQR(b+2);
printf("\n%d",a);
}

This gives answer 11 which completely baffles me.

Any suggestions on it will be highly appreciated.

Thanx in advance.
 
Old 12-20-2009, 11:50 AM   #2
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
I don't understand it either. It's like it's doing "a = sqr(b) + 2" instead of "a = sqr(b + 2)".
 
Old 12-20-2009, 12:09 PM   #3
JohnGraham
Member
 
Registered: Oct 2009
Posts: 467

Rep: Reputation: 139Reputation: 139
You have to be REALLLY REEEEEEEEEEEEEALLY careful with macros. To see why, we can get the c preprocessor to show us how it's expanded the macro:

Code:
$ cat > a.c << 'EOF'
> #define SQR(x) (x*x)
> main(){
> 
> int a,b=3;
> a=SQR(b+2);
> printf("\n%d",a);
> }
> EOF


$ gcc a.c -E
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.c"

main(){

int a,b=3;
a=(b+2*b+2);
printf("\n%d",a);
}
As you can see, SQR(b+2) gets expanded (correctly - i.e. this is not a bug in the preprocessor!) to (b+2*b+2), which will be evaluated as (b+(2*b)+2) since multiplication has higher precedence than addition.

This can be solved by defining SQR like:

Code:
#define SQR(x) ((x)*(x))
More generally, always put your arguments in parentheses each time they're used.



Note that there's still a flaw in this macro - a call to SQR(b++) would be expanded to ((b++)*(b++)), which is clearly not what you want. When you use a macro, you should try and only use each argument once, as it might have side effects.

You can cure this with:

Code:
#include <math.h>
#define SQR(x) pow((x),2)


John G
 
Old 12-20-2009, 12:09 PM   #4
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

The issue is "precedence":
Code:
/* BAD */
#define SQR(x) (x*x)
int
main()
{
  int a=2,b=3;
  a=SQR(b+2); 
  printf("\n%d",a);
  return 0;
}
Code:
/* BETTER */
#define SQR(x) ((x) * (x))
int
main()
{
  int a=2,b=3;
  a=SQR((b+2)); 
  printf("\n%d",a);
  return 0;
}
And here's why:
http://www.difranco.net/cop2220/op-prec.htm

Because the first example was actually doing this:
Code:
a = SQR(b+2*b+2)
        = 3 + (2*3) + 2
        = 11

Last edited by paulsm4; 12-20-2009 at 10:33 PM.
 
Old 12-20-2009, 12:14 PM   #5
btmiller
Senior Member
 
Registered: May 2004
Location: In the DC 'burbs
Distribution: Arch, Scientific Linux, Debian, Ubuntu
Posts: 4,290

Rep: Reputation: 378Reputation: 378Reputation: 378Reputation: 378
If you run cpp yourself on the source file, you'll see exactly why this is happening. Remember a #define is just a macro expansion for the preprocessor -- it just replaces one set of text with another, so your line becomes:

a=(b+2*b+2)

since b = 3, by order-of-operation (* takes operator precendence over +), the answer is clearly 11. To avoid this, change

a=SQR(b+2)

to

a=SQR((b+2))

or better yet, don't use macros for something that should be a function :-).
 
Old 12-20-2009, 01:13 PM   #6
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339

Rep: Reputation: 231Reputation: 231Reputation: 231
The multiplication is being done first.
Change it to:
Code:
#define SQR(x) ((x)*(x))
 
Old 12-20-2009, 09:20 PM   #7
man s
LQ Newbie
 
Registered: Dec 2009
Posts: 14

Original Poster
Rep: Reputation: 0
Thanx a lot guys!It was really helpful.
From what I got,the expansion is something like:

3+2*3+2
where order of precedence gives it 11.And since () has higher precedence than *,it gave the right answer.

Thanx again for the help.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
The C Preprocessor slzckboy Programming 9 04-15-2007 01:46 PM
C pre-preprocessor or preprocessor replacement Tischbein Programming 3 02-11-2007 11:38 AM
No C++ preprocessor Mandrake 10.1 ? TotalDefiance Linux - Software 1 11-04-2004 10:41 PM
Can the C preprocessor do this? MadCactus Programming 2 08-24-2004 01:29 AM
plz plz solve my route mapping problem nedian123 Linux - Networking 1 07-12-2004 09:41 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:31 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration