1071 words
5 minutes
Bit_Pattern_training_001

link#


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)v

Also, 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
./main

Example 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 = -1

Input: 25

Method 1 (comparison): sign = 0
Method 2 (unsigned shift): sign = 0
Method 3 (signed shift): sign = 0

Important: Sign indicator vs. mathematical sign#

Your original code computes:

InputResult
-25-1
00
250

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
./main

Expected results#

Methodv = -10v = 0v = 10
1. Comparison-100
2. Unsigned shift-100
3. Signed shift-100
4. Bitwise OR-101
5. Signed shift + OR-101
6. Portable sign-101
7. Non-negative011

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                           = -1

When v = 10:

(v != 0)                         = 1
(unsigned int)v >> 31            = 0
-(int)0                          = 0

1 | 0                            = 1

When 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_BIT is 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 == 8

1. 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 byte

Therefore:

sizeof(int) * CHAR_BIT

Calculates the total number of bits in an int:

4×8=32 bits4 \times 8 = 32 \text{ bits}

2. Understanding your expression#

(unsigned int)v >> (sizeof(int) * CHAR_BIT - 1)

Let’s break it down.

ExpressionMeaningTypical result
sizeof(int)Number of bytes in int4
CHAR_BITNumber of bits per byte8
sizeof(int) * CHAR_BITTotal bits32
... - 1Index of most significant bit31

So the expression becomes:

(unsigned int)v >> 31

This 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                                     0

Convert to unsigned and shift right by 31:

(unsigned int)v >> 31

Result:

00000000 00000000 00000000 00000001
                                      |
                                      1

For v = 10:

00000000 00000000 00000000 00001010

(unsigned int)v >> 31

00000000 00000000 00000000 00000000

4. Other useful macros in <limits.h>#

MacroMeaningTypical value
CHAR_BITBits per byte8
CHAR_MAXMaximum char value (if signed)127
INT_MAXMaximum int value2,147,483,647
INT_MINMinimum int value-2,147,483,648
UINT_MAXMaximum unsigned int value4,294,967,295
LONG_MAXMaximum long valuePlatform-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_BIT tells you how many bits are in one byte.
  • sizeof(int) * CHAR_BIT calculates the total bit width of an int.

This is particularly useful when writing low-level C code involving bit manipulation, CPU registers, integer representations, and binary operations.

Bit_Pattern_training_001
https://younghakim7.github.io/blog/posts/bit_pattern_training_001/
Author
YoungHa
Published at
2025-12-30