patterncMinor
Using bitwise operators with (unsigned long) instead of bitfields
Viewed 0 times
withunsignedlongbitfieldsinsteadbitwiseusingoperators
Problem
Here is my solution to Programming Exercise 15-7 from Stephen Prata's C Primer Plus, 6th Edition. This problem asks the reader to:
15-7
Write a program with the same behavior as described in exercise 6, but
use an unsigned long variable to hold the font information and
use the bitwise operators instead of bit members to manage the
information.
The previous exercise, referenced in the question, was:
15-6
Design a bit-field structure that holds the following information:
-
Font ID: A number in the range 0--255
-
Font Size: A number in the range 0--127
-
Alignment: A number in the range 0--2 representing the choices Left, Center, and Right
-
Bold: Off (0) or on (1)
-
Italic: Off (0) or on (1)
-
Underline: Off (0) or on (1)
Use this structure in a program that displays the font parameters and uses a looped menu to let the user change parameters....
...
[sample interaction here]
...
The program should use the & operator and suitable masks to ensure that the ID and size entries are converted to the specified range.
A sample run is provided that illustrates the desired formatting for a few interactions. I did not think that this was terribly pertinent to my question, but here is a Pastebin link to a text file containing the whole of both questions for anyone who is interested. There is an assignment at the beginning of
This code works and seems to handle bad inputs acceptably.
I am trying to better understand how to use bitwise operations. I am interested in any comments about the style or robustness of my code, especially as they pertain to its bitwise aspect or how I might have better used bitwise operations and better structured the font parameter bit assignments. I am not certain that I understood the last sentence of the question (15-6) about using "the
15-7
Write a program with the same behavior as described in exercise 6, but
use an unsigned long variable to hold the font information and
use the bitwise operators instead of bit members to manage the
information.
The previous exercise, referenced in the question, was:
15-6
Design a bit-field structure that holds the following information:
-
Font ID: A number in the range 0--255
-
Font Size: A number in the range 0--127
-
Alignment: A number in the range 0--2 representing the choices Left, Center, and Right
-
Bold: Off (0) or on (1)
-
Italic: Off (0) or on (1)
-
Underline: Off (0) or on (1)
Use this structure in a program that displays the font parameters and uses a looped menu to let the user change parameters....
...
[sample interaction here]
...
The program should use the & operator and suitable masks to ensure that the ID and size entries are converted to the specified range.
A sample run is provided that illustrates the desired formatting for a few interactions. I did not think that this was terribly pertinent to my question, but here is a Pastebin link to a text file containing the whole of both questions for anyone who is interested. There is an assignment at the beginning of
main() that sets font_params to match the starting point of the sample interaction.This code works and seems to handle bad inputs acceptably.
I am trying to better understand how to use bitwise operations. I am interested in any comments about the style or robustness of my code, especially as they pertain to its bitwise aspect or how I might have better used bitwise operations and better structured the font parameter bit assignments. I am not certain that I understood the last sentence of the question (15-6) about using "the
& operator and suitable masks to ensure that the IDSolution
-
An
-
Avoid an infinite loop
-
Consider specifying widths - easier to update/maintain.
-
Prefer to use matching types. Use
-
Watch out for assuming
-
Unclear why
An
int may be narrower than an unsigned long. Avoid unexpected behavior by using the correct type.unsigned long font_params = 0;
// font_params |= (1 << ID_OFFSET | 12 << SZ_OFFSET);
font_params |= (1ul << ID_OFFSET | 12ul << SZ_OFFSET);-
Avoid an infinite loop
// while (getchar() != '\n') continue;
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) continue;-
Consider specifying widths - easier to update/maintain.
// printf("%4s %4s %9s %3s %3s %3s\n", "ID", "SIZE", "ALIGNMENT", " B ", " I ", " U ");
// printf("%4lu %4lu %9s %3s %3s %3s\n",
// (params & FONT_ID) >> ID_OFFSET,
// (params & FONT_SZ) >> ID_OFFSET, ...
int w[6] = { 4,4,9,3,3,3 };
printf("%*s %*s %*s ...", w[0], "ID", w[1], "SIZE", w[2], "ALIGNMENT", ...
printf("%*lu %*lu %*s ...\n",
w[0], (params & FONT_ID) >> ID_OFFSET,
w[1], (params & FONT_SZ) >> ID_OFFSET, ...-
Prefer to use matching types. Use
unsigned long for strtoul() and size_t for strcspn().// size_t input;
unsigned long input;
input = strtoul(buf, &tailptr, 10);
size_t size;
// input = strcspn(options, buf);
size = strcspn(options, buf);-
Watch out for assuming
~ applies to the width of the target - it is applied to the constant. What if unsigned long was 64-bit, unsigned was 32-bit and FONT_SZ was 0xFE000000. ~FONT_SZ is an unsigned with the value of 0x01FFFFFF rather than 0xFFFFFFFF01FFFFFF, thus masking off the top bits. Same problem with ~0xFF anf ~0x7F. Better to use ~0xFFul, etc.unsigned long *params;
// *params &= ~FONT_SZ;
*params &= ~(1ul*FONT_SZ);
// or
*params |= FONT_SZ;
*params ^= FONT_SZ;
// or
#define FONT_SZ 0x0FE0ul-
Unclear why
char buf[BUFSIZE]; is so small (5). I'd expect a buffer width enough to handle the widest unsigned long value and then twice that. No reason to be stingy in buffer size in user input of a single number. #define ULONG_STR10_LEN (sizeof(unsigned long)*CHAR_BIT/3 + 1)
#define BUF_SIZE (ULONG_STR10_LEN*2 + 1 /* \n */ + 1 /* \0 */)
char buf[BUF_SIZE];`Code Snippets
unsigned long font_params = 0;
// font_params |= (1 << ID_OFFSET | 12 << SZ_OFFSET);
font_params |= (1ul << ID_OFFSET | 12ul << SZ_OFFSET);// while (getchar() != '\n') continue;
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) continue;// printf("%4s %4s %9s %3s %3s %3s\n", "ID", "SIZE", "ALIGNMENT", " B ", " I ", " U ");
// printf("%4lu %4lu %9s %3s %3s %3s\n",
// (params & FONT_ID) >> ID_OFFSET,
// (params & FONT_SZ) >> ID_OFFSET, ...
int w[6] = { 4,4,9,3,3,3 };
printf("%*s %*s %*s ...", w[0], "ID", w[1], "SIZE", w[2], "ALIGNMENT", ...
printf("%*lu %*lu %*s ...\n",
w[0], (params & FONT_ID) >> ID_OFFSET,
w[1], (params & FONT_SZ) >> ID_OFFSET, ...// size_t input;
unsigned long input;
input = strtoul(buf, &tailptr, 10);
size_t size;
// input = strcspn(options, buf);
size = strcspn(options, buf);unsigned long *params;
// *params &= ~FONT_SZ;
*params &= ~(1ul*FONT_SZ);
// or
*params |= FONT_SZ;
*params ^= FONT_SZ;
// or
#define FONT_SZ 0x0FE0ulContext
StackExchange Code Review Q#146421, answer score: 2
Revisions (0)
No revisions yet.