Bit Pattern Problem

F

fb

Hi Everyone. Thanks for the help with the qudratic equation problem...I
didn't think about actually doing the math...whoops. Anyway... I'm
having some trouble getting the following program to work. I want to
output a bit pattern from base 10 input. All I get is a zero after the
input...I've looked over the code but can't see the problem...any ideas?


/* display the bit pattern corresponding to
a signed decimal integer */

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int a, b, m, count, nbits;
unsigned mask;

/* determine the word size in bits and set the initial mask */
nbits = 8 * sizeof(int);
m = 0x1 << (nbits - 1); /* Place 1 in leftmost position */

/* main loop */
do {
/* read a signed integer */
printf("\n\nEnter an integer value (0 to stop): ", a);
scanf("%d", &a);

/* output the bit pattern */
mask = m;
for(count = 1; count <= nbits; count++); {
b = (a & mask) ? 1 : 0; /* set display bit on or off */
printf("%x", b); /* print display bit */
if (count % 4 == 0)
printf(" "); /* blank space after ever 4th digit */
mask >>= 1; /* shift mask 1 position to the right */
}
} while (a != 0);
return EXIT_SUCCESS; /* If it's there why not use it people! */
}
 
M

Mac

The error is on this line.

Well, the line shouldn't be written that way, but I doubt that is the
problem. If anything, it should be:

nbits = CHAR_BIT * sizeof (int);

--Mac
 
M

Mac

Hi Everyone. Thanks for the help with the qudratic equation problem...I
didn't think about actually doing the math...whoops. Anyway... I'm
having some trouble getting the following program to work. I want to
output a bit pattern from base 10 input. All I get is a zero after the
input...I've looked over the code but can't see the problem...any ideas?


/* display the bit pattern corresponding to
a signed decimal integer */

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int a, b, m, count, nbits;
unsigned mask;

/* determine the word size in bits and set the initial mask */
nbits = 8 * sizeof(int);
m = 0x1 << (nbits - 1); /* Place 1 in leftmost position */

/* main loop */
do {
/* read a signed integer */
printf("\n\nEnter an integer value (0 to stop): ", a);
scanf("%d", &a);

/* output the bit pattern */
mask = m;
for(count = 1; count <= nbits; count++); {

Someone else already pointed out that you didn't mean to put a semicolon
after your for loop. That collapses it to an empty loop.
b = (a & mask) ? 1 : 0; /* set display bit on or off */
printf("%x", b); /* print display bit */
if (count % 4 == 0)
printf(" "); /* blank space after ever 4th digit */
mask >>= 1; /* shift mask 1 position to the right */

I don't think the above line will do what you expect.

From the last public draft of c89:

3.3.7 Bitwise shift operators
[...]
The result of E1 >> E2 is E1 right-shifted E2 bit positions.
[...]
If E1 has a signed type and a negative
value, the resulting value is implementation-defined.

At the machine level, you sometimes see a shift with sign extension for
signed integers, and your implementation might use that type of shift
rather than a logic shift. What this means is that shifting a negative
number to the right may fill the higher order bits with 1's. The
documentation for your implementation should say what it does, though.

As far as I know, which may not be very far, every implementation will
probably either fill the high order bits with zeros or fill them with ones.
}
} while (a != 0);
return EXIT_SUCCESS; /* If it's there why not use it people! */
}

--Mac
 
C

CBFalconer

fb said:
.... snip ...
I'm having some trouble getting the following program to work.
I want to output a bit pattern from base 10 input. All I get is
a zero after the input...I've looked over the code but can't see
the problem...any ideas?

/* display the bit pattern corresponding to
a signed decimal integer */

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int a, b, m, count, nbits;
unsigned mask;

/* determine the word size in bits and set the initial mask */
nbits = 8 * sizeof(int);

m = 0x1 << (nbits - 1); /* Place 1 in leftmost position */

To do this m should be an unsigned int. Shifting into the sign
position results in undefined behavior. Unsigned ints don't have
a sign bit. Make all the variables unsigned.
/* main loop */
do {
/* read a signed integer */
printf("\n\nEnter an integer value (0 to stop): ", a);
^^^
What is this? You also need a "fflush(stdin);" after this.
scanf("%d", &a);

Check the result from scanf, which should be 1. Maybe:
if (1 != scanf("%ud", &a)) break;
/* output the bit pattern */
mask = m;
for(count = 1; count <= nbits; count++); {
^
What's this semicolon for?
b = (a & mask) ? 1 : 0; /* set display bit on or off */
printf("%x", b); /* print display bit */

simpler: putc(b + '0', stdout);
if (count % 4 == 0)
printf(" "); /* blank space after ever 4th digit */

simpler: putc(' ', stdout);
 
G

Gordon Burditt

/* read a signed integer */
^^^
What is this? You also need a "fflush(stdin);" after this.

No, you absolutely NEVER need a "fflush(stdin)". If you absolutely
have to invoke undefined behavior, use fflush(void main()). It will
probably save you a lot of time by failing to compile.

Gordon L. Burditt
 
D

Derrick Coetzee

Mac said:
I don't think the above line will do what you expect.

Nice try invoking UD on signed shift, but mask is unsigned. It was
merely assigned from a signed variable, but I think that's well-defined
with two's-complement semantics. As an aside, in my experience, even
signed variable shifts typically get compiled into logical rather than
arithmetic shifts.
 
W

William L. Bahn

fb said:
Hi Everyone. Thanks for the help with the qudratic equation problem...I
didn't think about actually doing the math...whoops.

It's actually a very, very big oops that I hope you learn from
and don't just hand wave it.

Computers are really, really stupid. They crunch numbers - and
that's about it. It is up to YOU to solve the problem. Before you
start coding you should try some hand cases and crank the math
and you should especially do that as soon as a problem arises.
There seems to be an ever increasing trend towards just wanting
to throw code at the compiler without understanding what that
code does or is even supposed to do. Don't let yourself fall into
that trap.
Anyway... I'm
having some trouble getting the following program to work. I want to
output a bit pattern from base 10 input. All I get is a zero after the
input...I've looked over the code but can't see the problem...any ideas?

All you get is "a zero"? As in a single zero? Even though you
have a loop that is guaranteed to print out something every time
through it? What does that tell you? Either the test only passes
the first time through, or the loop code isn't the code you think
it is. If examining the code with this in mind doesn't tell you
something, then instrument the loop by printing out the value of
count within the body of the loop. If it prints out "1" then the
loop is only executing once - look for something in the loop that
is changing one of the values in the test expression. If it
prints out a "9" then what you thought was the loop is not
actually part of the loop. There's a REAL common mistake that can
result in that - so learning how to track it down through
systematic debugging when the Mark II eyeballs insist on skipping
over it (which that are want to do because, as a human with a
functioning human brain, you automatically tend to see what you
WANT the code to be instead of what the code actually IS) can be
a very valuable lesson. I'll leave it for you to track down this
problem further.

You have another potential problem in that any time you do right
shift operations on signed integers, you don't know for sure what
it going to get shifted in to the vacated bit position. You also
don't know for sure how negative values are represented - but
that's sort of the point of the exercise, isn't it?

This is my take on performing any kind of bit banging - the folks
that wrote C intended it to be primarily a high level language
where the programmer worked with "values" and not
"representations". They therefore primarily define how the
different operations behave with respect to the values being
represented and not the representations themselves. They leave it
up to the compiler designer to make that happen and leave them
free to play whatever games they like to (subject to a few
constraints) with the internal representations. But, they
recognize that a few people will have the need/desire to do bit
banging and so they defined a minimal set of operations that have
to have completely well-defined effects on the internal
representation - but imposing this constraint imposes unnecessary
limitations on the games the compiler writer can play in working
with the "values", so the ONLY data type (as far as I know) that
they included in this tightly constrained bit-level definition
are the unsigned integers. Not the integers, only the unsigned
integers. Therefore, only bit bang unsigned integers.
 
W

William L. Bahn

fb said:
right-o thanks.

So....that told you what the problem is?

Watch out - you're hand waving it. I get the impression you
aren't trying to understand what the problem is, you are just
wanting someone to tell you what code to throw at the compiler.
Otherwise you should have asked what could possibly be wrong with
that line. It should work for you - but it is not robust and,
conceivably, might not work on your machine - and even if it did
have a problem it wouldn't yield the result you are experiencing.

But I'm not getting the impression that understanding the
relationship between your code and the results your code produce
is very high on your priority list.
 
W

William L. Bahn

Derrick Coetzee said:
Nice try invoking UD on signed shift, but mask is unsigned. It was
merely assigned from a signed variable, but I think that's well-defined
with two's-complement semantics.

But what is the basis for assuming two's complement semantics?

Even if it is, let's say that I have a four bit two's complement
value represented as 1000 stored in a signed variable m. What
value is that? What value will get stored in the four bit
unsigned variable n if I use n=m ?

As assignments between signed and unsigned data types of the same
basic type required to copy the bit pattern if the value in the
expression can't be represented in the type of the object being
assigned to? Or is this undefined behavior?
As an aside, in my experience, even
signed variable shifts typically get compiled into logical rather than
arithmetic shifts.

That's been the exact opposite of mine. For instance, the
following code:

#include <stdio.h>
int main(void)
{
int i;

i = -8;
printf("%i %i\n", i, i >> 1);
return 0;
}

printed:

-8 -4

(Using Borland TurboC/C++ v4.5)
 
P

pete

William L. Bahn wrote:
As assignments between signed and unsigned data types of the same
basic type required to copy the bit pattern if the value in the
expression can't be represented in the type of the object being
assigned to? Or is this undefined behavior?

Assigning an out of range value to a signed integer,
is implementation defined.
To assign a negative value to an unsigned,
(UINT_MAX + 1) is added to the value until it becomes non negative.
To assign an out of range positive value to an unsigned,
(UINT_MAX + 1) is subtracted until the value is in range.
 
P

pete

fb said:
I want to output a bit pattern from base 10 input.

/* display the bit pattern corresponding to
a signed decimal integer */

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>

#define LENGTH 80
#define str(x) # x
#define xstr(x) str(x)

void bitstr(char *, void const *, size_t);

int main(void)
{
int a, rc;
char abits[CHAR_BIT * sizeof a + 1], string[LENGTH + 1];

fputs("\n\nEnter an integer value (0 to stop): ", stdout);
fflush(stdout);
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", string);
if (!feof(stdin)) {
getchar();
}
while (rc == 1) {
a = atoi(string);
bitstr(abits, &a, sizeof a);
printf(" %s = %d\n", abits, a);
if (a == 0) {
break;
}
fputs("\n\nEnter an integer value (0 to stop): ", stdout);
fflush(stdout);
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", string);
if (!feof(stdin)) {
getchar();
}
}
return 0;
}

void bitstr(char *str, const void *obj, size_t n)
{
unsigned mask;
const unsigned char *byte = obj;

while (n--) {
mask = ((unsigned char)-1 >> 1) + 1;
do {
*str++ = (char)(mask & byte[n] ? '1' : '0');
mask >>= 1;
} while (mask != 0);
}
*str = '\0';
}
 
A

Alex Fraser

pete said:
Assigning an out of range value to a signed integer,
is implementation defined.
To assign a negative value to an unsigned,
(UINT_MAX + 1) is added to the value until it becomes non negative.

(or, obviously, ULONG_MAX + 1 etc, according to the type of the object being
assigned to.)

....which, if the negative value can be represented using two's complement in
the number of value bits in the unsigned integer, leaves the unsigned
integer with the two's complement representation of the negative value.

In many cases this means that assignment of a signed integer type to the
corresponding unsigned integer type does indeed simply copy the bit pattern.
To assign an out of range positive value to an unsigned,
(UINT_MAX + 1) is subtracted until the value is in range.

Alex
 
C

CBFalconer

Gordon said:
No, you absolutely NEVER need a "fflush(stdin)". If you absolutely
have to invoke undefined behavior, use fflush(void main()). It will
probably save you a lot of time by failing to compile.

Did I actually write stdin? Must be the cat on the keyboard.
Obviously I meant stdout. Thanks for the correction.
 
B

Barry Schwarz

Hi Everyone. Thanks for the help with the qudratic equation problem...I
didn't think about actually doing the math...whoops. Anyway... I'm
having some trouble getting the following program to work. I want to
output a bit pattern from base 10 input. All I get is a zero after the
input...I've looked over the code but can't see the problem...any ideas?


/* display the bit pattern corresponding to
a signed decimal integer */

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int a, b, m, count, nbits;
unsigned mask;

/* determine the word size in bits and set the initial mask */
nbits = 8 * sizeof(int);
m = 0x1 << (nbits - 1); /* Place 1 in leftmost position */

/* main loop */
do {
/* read a signed integer */
printf("\n\nEnter an integer value (0 to stop): ", a);

a is uninitialized. You cannot pass it to a function in this state,
even if the function will not attempt to evaluate it. This invokes
undefined behavior. In this case, you probably don't want to pass it
at all anyway.

snip


<<Remove the del for email>>
 
B

Barry Schwarz

Assigning an out of range value to a signed integer,
is implementation defined.

No, it is undefined.
To assign a negative value to an unsigned,
(UINT_MAX + 1) is added to the value until it becomes non negative.
To assign an out of range positive value to an unsigned,
(UINT_MAX + 1) is subtracted until the value is in range.



<<Remove the del for email>>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
EmeliaBryc

Latest Threads

Top