Fog Creek Software
Discussion Board

programming in c

Hi all
My attempts to do this exercice (found in K&R) lead me
to the following code. The problem is that I don't know
if my code is doing is job. I'm used to irc, but I don't really
get great help there. I don't know if it is right to ask
for help in this forum, but I'm asking anyway.

This is the exercice
Write a function setbits(x,p,n,y) that returns
x with the n bits that begin at position p set to the rightmost
n bits of y, leaving the other bits unchanged.

And this is my code:

int main()
        unsigned x,y;
        x = 14;
        y = 13;

        printf("Test for the setbits function.");
        printf("\nx=%d  y=%d",x,y);
        printf("\nAfter passing x and y to the function");

        return 0;

int setbits(unsigned x, int p, int n, unsigned y)
        return (x | ((y & ~(~0 << n)) << (p + 1)));

Thanks in advance for any help you might be able to provide.

Monday, April 26, 2004

> The problem is that I don't know if my code is doing its
> job.

You should learn how to use a debugger. That's what it is there for! You don't have a debugger-phobia, do you? Some people hate to single step through code, especially assembly code!

Single step through your code and see what happens and don't even start with the recursion thing being hard to debug. Your debugger will be able to handle that. It'll teach you either how the stack works or how to have a plan for debugging code that you are writing.

Monday, April 26, 2004

No - you have to clear the rightmost bits of x.  A test:
if X is 0xFFFF and Y is 0x0, with p=15 and
n = 16, you should get 0xFF00 as your answer.  You'll
get 0xFFFF.  (I'm not sure whether the position is 0 based
or 1 based and I'm too lazy to check :) but I'm assuming
32 bit integers with positions numbered 0 through 31)

Also, your printf's should use %x instead of %d so you
don't have to do decimal to binary conversions - hex to
binary is much easier for me at least.

Monday, April 26, 2004

After you work through a problem, you can check your code versus the code on Kamilche's K&R C pages:

I found them helpful when working through the book.

yet another anon
Monday, April 26, 2004

Thanks a lot for your help.
By that way, the only debugger I've come across is the old dos debug.exe, I don't know if it can debug such code.
And I have heard that the other debugger are different from debug.exe
Can you suggest a debugger??

(PS: I don't think my compiler (bcc55 command line)  have one)

Tuesday, April 27, 2004

> By that way, the only debugger I've come across is the old dos debug.exe, I don't know if it can debug such code.

It can't do source-level debugging.

Without a debugger, people usually 'debug' their software by inserting extra printf statements; your example probably had enough printf statements, but you could insert more inside setbits for example if you want to know the value of subexressions like "~(~0 << n))".

I suggest that you think of and write down a good liist of x,p,n, and y values with which to test your software. For example, what is the expected output when x=0xffff, p=3, n=2, y=0xcccc?  Use these values to test your software (calculated the expected answers, and verify that the software gives these answers). Also, consider what correct behaviour should be in unusual cases, such as "(16-p) < n".

> Can you suggest a debugger??

Perhaps "Turbo C" ... it's an integrated compiler and debugger (an IDE, Integrated Development Environment), apparently free now:,1410,20841,00.html

Or, stop using DOS, and use Linux instead ... then, you could use free tools like gcc and gdb.

Christopher Wells
Tuesday, April 27, 2004

thanks a lot Christopher

Tuesday, April 27, 2004

I agree that learning to use a debugger is a good skill, but I don't think it will help much in this particular case.  In this case the problem is that the expression looks like someone is blowing into a modem:

(x | ((y & ~(~0 << n)) << (p + 1)));

I look at that thing and don't have the faintest idea what it does.  Break it down.  First, come up with a plan.  How about this:

1) Create a temporary variable to hold the return value.
2) Copy the bits of x into the return value.
3) Zero out the bits that we are going to change.
4) Create a temporary variable to hold the new bits.
5) Copy the bits from y into the new bits.
6) Shift the bits to the right position
7) "Or" the new bits into the old bits.
8) Return.

Step three could probably be broken down a little more.  We'll do that by creating yet another temp variable and use it as a mask.  How are we going to calculate that thing?  We could have an "upper mask" and a "lower mask" and combine them together.

Now translate the plan into action.

unsigned int retval,  mask, uppermask, lowermask, newbits;
retval = x;
uppermask = (~0) << (p+1);
lowermask = ~((~0) << (p+1-n));
mask = uppermask | lowermask;
retval = retval & mask;
newbits = y;
newbits = newbits << (p + 1 - n);
newbits = newbits & (~mask);
retval = retval | newbits;
return retval;

Are there bugs in the algorithm above?  Maybe.  I'm just typing this up as I go here,I'm not running it through a compiler or testing it or anything.  But since I've broken each logical operation down into one line of code, if there is a bug it is going to be MUCH easier to figure out where things went wrong, than if it is one godawful line of unreadable boolean logic.

That's a ten line algorithm compared to your one liner.  Does it take ten times as long to run?  Of course not, unless your compiler vendor writes a really, really bad compiler.  Modern compilers are smart enough to optimize code like the above into tight machine code. 

Remember, code is a lot harder to READ than it is to WRITE.  Write your code as if someone clueless is going to be reading it -- because in a couple days/weeks/months, that clueless dev could be you!  It is very easy to forget how a piece of code works.

Eric Lippert
Tuesday, April 27, 2004

*  Recent Topics

*  Fog Creek Home