Have I done them right?

C

Curious Student

I'd be obliged if someone could validate the functions I've written
below from the try-it-yourself excercises of K&R:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void DWordToWords(const int DWord, short int* LoWord, short int*
HiWord);
void MakeDWord(const short LoWord, const short HiWord, int* DWord);
unsigned GetBits(unsigned, int, int);
unsigned SetBits(unsigned, int, int, int);
unsigned Invert(unsigned, int, int);


/*int main(void)
{
	int DWord;
	short LoWord, HiWord;
	
	DWord = 1066825727;
	LoWord = HiWord = 0;

	DWordToWords(DWord, &LoWord, &HiWord);
	printf("DWord = %d\nLoWord = %d\nHiWord = %d\n\n", DWord, LoWord,
HiWord);

	DWord = 0;
	MakeDWord(LoWord, HiWord, &DWord);
	printf("DWord = %d\nLoWord = %d\nHiWord = %d\n\n", DWord, LoWord,
HiWord);
}*/


void DWordToWords(const int DWord, short int* LoWord, short int*
HiWord)
{
	
	*LoWord = DWord & ~(~0<<16);
	*HiWord = DWord>>16;
}

void MakeDWord(const short LoWord, const short HiWord, int* DWord)
{
	*DWord = HiWord<<16;
	*DWord |= LoWord;
}

unsigned int GetBits(unsigned x, int p, int n)
{
	/*gets the right-adjusted n bits of integer x 
	starting from position p*/
	return (x>>(p-n+1)) & ~(~0<<(p-n));
}

unsigned int SetBits(unsigned x, int p, int n, int y)
{
	/*set n bits of integer x starting from position 
	p to the right-most n bits in integer y*/
	y&=~(~0<<n);
	return x|((y&~(~0<<n))<<(p-n+1));
}

unsigned Invert(unsigned x, int p, int n)
{
	/*Inverts n bits in x starting from position p*/
	int temp=GetBits(x, p, n);
	temp=~temp;
	return SetBits(x, p, n, temp);
}
 
M

Malcolm

Curious Student said:
I'd be obliged if someone could validate the functions I've written
below from the try-it-yourself excercises of K&R:
The exercise is a bit out of date. On many platforms an int is 32 bits
whilst shorts are 16 bits, but this is by no means universal, nor are you
guaranteed that two shorts fit in an int.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void DWordToWords(const int DWord, short int* LoWord, short int*
HiWord);
[/QUOTE]
void DWordToWords(int x, short *lo, short *hi)
The "const" is useless. "short" is conventional for "short int". The
prototype is also easier to read if you use shorter variable names (a bit of
a matter of taste, this).[QUOTE]
void MakeDWord(const short LoWord, const short HiWord, int* DWord);
unsigned GetBits(unsigned, int, int);
unsigned SetBits(unsigned, int, int, int);
unsigned Invert(unsigned, int, int);


/*int main(void)
{
int DWord;
short LoWord, HiWord;[/QUOTE]
short LOWord = 0;
short HiWord = 0;[QUOTE]
DWord = 1066825727;
LoWord = HiWord = 0;

DWordToWords(DWord, &LoWord, &HiWord);
printf("DWord = %d\nLoWord = %d\nHiWord = %d\n\n", DWord, LoWord,
HiWord);

DWord = 0;
MakeDWord(LoWord, HiWord, &DWord);
printf("DWord = %d\nLoWord = %d\nHiWord = %d\n\n", DWord, LoWord,
HiWord);
}*/


void DWordToWords(const int DWord, short int* LoWord, short int*
HiWord)
{

*LoWord = DWord & ~(~0<<16);
*HiWord = DWord>>16;
}
[/QUOTE]
This function relies on shorts being 16 bits and ints being 32. You could
just write
*LoWord = DWord & 0xFFFF;[QUOTE]
void MakeDWord(const short LoWord, const short HiWord, int* DWord)
{
*DWord = HiWord<<16;
*DWord |= LoWord;
}[/QUOTE]
Same thing applies to this function.[QUOTE]
unsigned int GetBits(unsigned x, int p, int n)
{
/*gets the right-adjusted n bits of integer x
starting from position p*/
return (x>>(p-n+1)) & ~(~0<<(p-n));
}

unsigned int SetBits(unsigned x, int p, int n, int y)
{
/*set n bits of integer x starting from position
p to the right-most n bits in integer y*/
y&=~(~0<<n);
return x|((y&~(~0<<n))<<(p-n+1));
}
[/QUOTE]
Assuming these functions work you could use them to implement a more
portable dword to words function.[QUOTE]
unsigned Invert(unsigned x, int p, int n)
{
/*Inverts n bits in x starting from position p*/
int temp=GetBits(x, p, n);
temp=~temp;
return SetBits(x, p, n, temp);
}
[/QUOTE]
 What do you intend to use this one for?[QUOTE]
 
J

Jack Klein

On 19 Jun 2004 14:31:00 -0700, (e-mail address removed) (Curious
Student) wrote in comp.lang.c:

There are some very serious dependencies on types here.
I'd be obliged if someone could validate the functions I've written
below from the try-it-yourself excercises of K&R:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void DWordToWords(const int DWord, short int* LoWord, short int*
HiWord);
void MakeDWord(const short LoWord, const short HiWord, int* DWord);
unsigned GetBits(unsigned, int, int);
unsigned SetBits(unsigned, int, int, int);
unsigned Invert(unsigned, int, int);


/*int main(void)
{
	int DWord;
	short LoWord, HiWord;
	
	DWord = 1066825727;[/QUOTE]

There is no guarantee that this value can be represented in an int.
The C standard requires that an int be able to represent values in the
range of -32767 to +32767.

There is also no guarantee in the C standard that an int has any
greater range of values than a short int.
[QUOTE]
LoWord = HiWord = 0;

	DWordToWords(DWord, &LoWord, &HiWord);
	printf("DWord = %d\nLoWord = %d\nHiWord = %d\n\n", DWord, LoWord,
HiWord);

	DWord = 0;
	MakeDWord(LoWord, HiWord, &DWord);
	printf("DWord = %d\nLoWord = %d\nHiWord = %d\n\n", DWord, LoWord,
HiWord);
}*/


void DWordToWords(const int DWord, short int* LoWord, short int*
HiWord)
{
	
	*LoWord = DWord & ~(~0<<16);[/QUOTE]

On a platform with 16 bit ints, this shift overflows and produces
undefined behavior.
[QUOTE]
*HiWord = DWord>>16;[/QUOTE]

As does this one.
[QUOTE]
}

void MakeDWord(const short LoWord, const short HiWord, int* DWord)
{
	*DWord = HiWord<<16;[/QUOTE]

In this case, the short HiWord is promoted to int and left shifted 16
places.  Again, if int has 16 bits the behavior is undefined.
[QUOTE]
*DWord |= LoWord;
}[/QUOTE]

You don't call the next three functions in this program but they are
all extremely dangerous if passed improper values of p and n.  If the
expression "p-n+1" evaluates to less than 0, or greater than the width
of an int in bits, you have undefined behavior again.
[QUOTE]
unsigned int GetBits(unsigned x, int p, int n)
{
	/*gets the right-adjusted n bits of integer x 
	starting from position p*/
	return (x>>(p-n+1)) & ~(~0<<(p-n));
}

unsigned int SetBits(unsigned x, int p, int n, int y)
{
	/*set n bits of integer x starting from position 
	p to the right-most n bits in integer y*/
	y&=~(~0<<n);
	return x|((y&~(~0<<n))<<(p-n+1));
}

unsigned Invert(unsigned x, int p, int n)
{
	/*Inverts n bits in x starting from position p*/
	int temp=GetBits(x, p, n);
	temp=~temp;
	return SetBits(x, p, n, temp);
}
 

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

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,190
Latest member
ClayE7480

Latest Threads

Top