link
- 1. Clear lowest set bit
- 2. Extract lowest set bit
- 3. Check power of two
- 4. Set bits below lowest set bit
- 5. Clear trailing ones
- 6. Find lowest zero bit
- 7. Binary → Gray code
- 8. Gray → Binary
- 9. Test bit
- 10. Toggle bit
- 11. Clear bit
- 12. Set bit
- 13. Align to power-of-two boundary
- 14. Branchless min/max
- 15. Fast popcount step
Operator Truth Table 기초
만들면서 익히기
Here is the corrected, complete C program with main(), printf(), and user input.
Complete C code (main.c)
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("Compute the sign of an integer\n");
int v;
int sign;
printf("Enter an integer: ");
if (scanf("%d", &v) != 1) {
printf("Invalid input.\n");
return 1;
}
// Method 1: Portable C
// Returns -1 if v < 0, otherwise 0.
sign = -(v < 0);
printf("\nMethod 1 (comparison): sign = %d\n", sign);
// Method 2: Extract the sign bit using unsigned shift.
// Assumes int and unsigned int have the same width
// and int uses the conventional signed representation.
sign = -(int)((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1));
printf("Method 2 (unsigned shift): sign = %d\n", sign);
// Method 3: Implementation-defined behavior.
// Right-shifting a negative signed integer is
// implementation-defined in C.
sign = v >> (sizeof(int) * CHAR_BIT - 1);
printf("Method 3 (signed shift): sign = %d\n", sign);
return 0;
}
Important correction: Your original Method 2 had an unnecessary conversion:
(unsigned int)((int)v)The simpler expression is:
(unsigned int)vAlso, Method 2 extracts the most significant bit, so it assumes a conventional signed integer representation. The original expression -(int)(...) then converts that bit into 0 or -1.
Compile and run
gcc -Wall -Wextra -std=c11 -O2 main.c -o main
./mainExample output
Input: -25
Compute the sign of an integer
Enter an integer: -25
Method 1 (comparison): sign = -1
Method 2 (unsigned shift): sign = -1
Method 3 (signed shift): sign = -1Input: 25
Method 1 (comparison): sign = 0
Method 2 (unsigned shift): sign = 0
Method 3 (signed shift): sign = 0Important: Sign indicator vs. mathematical sign
Your original code computes:
| Input | Result |
|---|---|
-25 | -1 |
0 | 0 |
25 | 0 |
If you want the mathematical sign function (-1, 0, 1), use:
sign = (v > 0) - (v < 0);This is the most portable and straightforward solution in C.
Here is the complete C program with all five methods added, including printf() output to compare their results.
Complete C code (main.c)
#include <stdio.h>
#include <limits.h>
int main(void) {
int v;
int sign;
printf("====================================\n");
printf(" Compute Integer Sign\n");
printf("====================================\n");
printf("Enter an integer: ");
if (scanf("%d", &v) != 1) {
printf("Invalid input.\n");
return 1;
}
printf("\nInput value: %d\n\n", v);
// Method 1: Comparison (returns -1 or 0).
sign = -(v < 0);
printf("Method 1 (comparison): %d\n", sign);
// Method 2: Unsigned shift (returns -1 or 0).
sign = -(int)((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1));
printf("Method 2 (unsigned shift): %d\n", sign);
// Method 3: Signed shift (less portable).
sign = v >> (sizeof(int) * CHAR_BIT - 1);
printf("Method 3 (signed shift): %d\n", sign);
// Method 4: Sign function (-1, 0, or +1).
sign = (v != 0) | -(int)((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1));
printf("Method 4 (bitwise OR): %d\n", sign);
// Method 5: Signed shift (less portable).
sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1));
printf("Method 5 (signed shift): %d\n", sign);
// Method 6: Portable mathematical sign function.
sign = (v > 0) - (v < 0);
printf("Method 6 (portable): %d\n", sign);
// Method 7: Non-negative test (returns 0 or +1).
sign = 1 ^ ((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1));
printf("Method 7 (non-negative): %d\n", sign);
printf("\n====================================\n");
return 0;
}
Compile and execute
gcc -Wall -Wextra -std=c11 -O2 main.c -o main
./mainExpected results
| Method | v = -10 | v = 0 | v = 10 |
|---|---|---|---|
| 1. Comparison | -1 | 0 | 0 |
| 2. Unsigned shift | -1 | 0 | 0 |
| 3. Signed shift | -1 | 0 | 0 |
| 4. Bitwise OR | -1 | 0 | 1 |
| 5. Signed shift + OR | -1 | 0 | 1 |
| 6. Portable sign | -1 | 0 | 1 |
| 7. Non-negative | 0 | 1 | 1 |
Important: How Method 4 works
Consider:
sign = (v != 0) |
-(int)((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1));For a conventional 32-bit int:
When v = -10:
(v != 0) = 1
(unsigned int)v >> 31 = 1
-(int)1 = -1
1 | -1 = -1When v = 10:
(v != 0) = 1
(unsigned int)v >> 31 = 0
-(int)0 = 0
1 | 0 = 1When v = 0:
(v != 0) = 0
(unsigned int)v >> 31 = 0
-(int)0 = 0
0 | 0 = 0- Recommended
- For ordinary C programming, use:
sign = (v > 0) - (v < 0);- It is portable, concise, and does not depend on signed integer representation or implementation-defined right shifts.
CHAR_BIT
CHAR_BITis a C standard macro defined in the header<limits.h>. It represents the number of bits in one byte.
#include <limits.h>For most modern computers:
CHAR_BIT == 81. Why do we need CHAR_BIT?
In C, sizeof(int) returns the size of an int in bytes, not bits.
For example, on a typical 32-bit int system:
sizeof(int) = 4 // 4 bytes
CHAR_BIT = 8 // 8 bits per byteTherefore:
sizeof(int) * CHAR_BITCalculates the total number of bits in an int:
2. Understanding your expression
(unsigned int)v >> (sizeof(int) * CHAR_BIT - 1)Let’s break it down.
| Expression | Meaning | Typical result |
|---|---|---|
sizeof(int) | Number of bytes in int | 4 |
CHAR_BIT | Number of bits per byte | 8 |
sizeof(int) * CHAR_BIT | Total bits | 32 |
... - 1 | Index of most significant bit | 31 |
So the expression becomes:
(unsigned int)v >> 31This shifts the unsigned integer right by 31 positions, leaving its most significant bit in bit position 0.
3. Visual example (32-bit integer)
For v = -10, assuming conventional 32-bit two’s-complement representation:
(int)v:
11111111 11111111 11111111 11110110
| |
31 0Convert to unsigned and shift right by 31:
(unsigned int)v >> 31Result:
00000000 00000000 00000000 00000001
|
1For v = 10:
00000000 00000000 00000000 00001010
(unsigned int)v >> 31
00000000 00000000 00000000 000000004. Other useful macros in <limits.h>
| Macro | Meaning | Typical value |
|---|---|---|
CHAR_BIT | Bits per byte | 8 |
CHAR_MAX | Maximum char value (if signed) | 127 |
INT_MAX | Maximum int value | 2,147,483,647 |
INT_MIN | Minimum int value | -2,147,483,648 |
UINT_MAX | Maximum unsigned int value | 4,294,967,295 |
LONG_MAX | Maximum long value | Platform-dependent |
You can inspect these values with:
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("CHAR_BIT = %d\n", CHAR_BIT);
printf("sizeof(int) = %zu bytes\n", sizeof(int));
printf("int bits = %zu\n", sizeof(int) * CHAR_BIT);
printf("INT_MAX = %d\n", INT_MAX);
printf("INT_MIN = %d\n", INT_MIN);
printf("UINT_MAX = %u\n", UINT_MAX);
return 0;
}Key takeaway:
sizeof(int)measures bytes.CHAR_BITtells you how many bits are in one byte.sizeof(int) * CHAR_BITcalculates the total bit width of anint.
This is particularly useful when writing low-level C code involving bit manipulation, CPU registers, integer representations, and binary operations.