Tuesday, December 4, 2007

* and \*

I was coding from past 25 minutes in my favorite language C (that's because this is the only language I know :-).

Any ways I was writing a program which could evaluate reverse Polish expressions taking input from command line (yeah yeah you must be thinking pretty simple, what's so special). The logic of the program is very simple. You just push any incoming operand in the argument list to a stack and whenever any operator comes you just pop last two operands and push the result back to the stack after operating them with the operator.

Well I wrote the code and started testing it.

$./a.out 2 3 4 + *
$0


I was surprised and thought a bug might have been crept in and checked the code for logical errors. But hey I guess my logic ain't bad. Then I threw the dice another way.

$./a.out 2 3 +
$5

which is the correct output.

Now comes the funny part. I had faith only in GDB. So I ran a GDB session.

$gcc -g expr.c
$gdb ./a.out
(gdb)run 2 3 4 + *


Yes, to pass arguments when you are debugging your code using GDB, you have to specify the arguments on the (gdb) prompt when you are going to run it using run or r. I checked the values of different variables. The first culprit was argc or argument count it's value was 19 it was supposed to be 6. I just checked the first few starting lines. Everything was going on fine. Push and Pop operations to the stack, conversion of strings i.e. "2" to integer 2 everything was cool. Then suddenly when i checked the value of *argv it showed itoa.c which is another C source file in my current directory. I was surprised what the hell was going on. After scratching my head for another five minutes I typed following on the command line.

$./a.out 2 3 4 + \*
$14


It's the right output.

The problem I was facing is that the gnulinux shell considers * as wild card character meaning any number of character. So when I passed * to the program I was actually passing all the files currently present in my current directory so the result was erroneous and when I passed \* I was actually telling the shell that it was '*' not the name of all the files present in my current directory. So GDB saved the day.

Moral of the *experience*..

1. Avoid hand-hacking. Had I tried solving the problem without using GDB, I would have wasted my precious hours.

2. When passing wild cards to a program on the Shell escape them using \ unless you really mean them to be wild cards.

3. Free Software is great.

2 comments:

Kazim Zaidi said...

Great learning experience for you, Waseem!

But do you know there's one special situation where * will do multiplication for you, without needing to escape it using \ or using quotes.

Can you find when would this happen?

If you're stuck, you can refer to Rob Pike's Unix Programming Environment.

Waseem Ahmad said...

Yeah I'm thinking about reading that book in the coming winter vacations..I have heard a lot about this book....And I will do a search for the situation.