BIT102 C Programming

C ProgrammingUnit 215 min read

Data Types, Variables, Operators & Bitwise Logic in C

Unit 2 of C Programming covers fundamental building blocks: fundamental data types (integer, float, char), their ranges and storage sizes; variable declaration and scope (local vs. global); arithmetic, relational, logical, and bitwise operators with precedence/associativity rules; and practical applications like file m

TAKEAWAYS:

  • Understand 8 fundamental data types (int, float, char, etc.) and their storage sizes/range limits (e.g., int is 2 bytes in TU’s 16-bit systems, float uses 4 bytes for 7-digit precision).
  • Master variable scope rules: global variables persist program-wide but risk unintended side effects; local variables are safer but limited to blocks.
  • Bitwise operators (&, |, ^, <<, >>) manipulate individual bits—critical for low-level tasks like Khalti’s transaction hashing or NTC’s network packet compression.
  • Operator precedence follows PEMDAS (Parentheses > Exponents > Multiplication > Division > Addition > Subtraction), but bitwise operators have higher priority than comparisons.
  • Expressions combine operators and operands; associativity (left-to-right for +, right-to-left for ^) dictates evaluation order.
  • File handling (e.g., merging num1.txt and num2.txt) uses fopen(), fscanf(), and fprintf()—a core skill for eSewa’s payment logs or NEPSE’s stock data processing.

Core Concepts: Data Types and Storage

1. Fundamental Data Types in C

C provides 8 fundamental data types, each with a specific size (in bytes) and range of values. The ranges depend on the system’s word size (e.g., 16-bit vs. 32-bit). In TU’s context (often 16-bit systems), assume:

Data Type Size (bytes) Range Example Use Case
int 2 to Storing Ncell’s call duration (seconds)
float 4 to Calculating Daraz’s shipping cost (with 7-digit precision)
char 1 to (signed) or to (unsigned) Storing eSewa’s transaction status (e.g., 'S' for success)
double 8 to Financial calculations (e.g., bank interest rates)
long 4 to Large counters (e.g., Pathao’s ride IDs)
short 2 Same as int (often) Compact storage (e.g., NTC’s meter readings)

Why ranges matter:

  • Overflow: Assigning 32768 to an int causes undefined behavior (wraps to ).
  • Precision: float loses precision for large numbers (e.g., 123456789.0 becomes 123456000.0).
  • Memory: char is ideal for single characters (e.g., menu options in Khalti’s app).

2. Variable Declaration and Scope

Variables store data in memory. Their scope determines where they can be accessed:

  • Local variables: Declared inside a block (e.g., if, for, function). Exist only while the block executes.
  • Global variables: Declared outside all functions. Accessible everywhere but risk side effects.
#include <stdio.h>
int global = 10; // Global variable

void example() {
    int local = 20; // Local variable
    printf("Global: %d, Local: %d\n", global, local);
}

int main() {
    example();
    // printf("%d", local); // ERROR: local is out of scope
    return 0;
}

Output:

Global: 10, Local: 20

Advantages/Disadvantages of Global Variables:

Advantages Disadvantages
Accessible across functions Can be modified unintentionally
Reduces need for parameter passing Hard to debug (unpredictable state)
Useful for constants (e.g., PI = 3.14) Encourages poor modular design

Real-World Example:

  • eSewa’s Transaction System:
    • Global: MAX_TRANSACTIONS = 1000 (constant).
    • Local: amount, user_id inside process_payment() function.

Operators: The Building Blocks of Logic

1. Arithmetic Operators

Perform mathematical operations. Precedence: * and / before + and -.

Operator Name Example Result
+ Addition 5 + 3 8
- Subtraction 10 - 4 6
* Multiplication 3 * 4 12
/ Division 10 / 3 3 (integer division)
% Modulus 10 % 3 1

Example: Calculate Ncell’s billing for 5 minutes at Rs. 2/min.

int minutes = 5, rate = 2;
int cost = minutes * rate; // 10
printf("Bill: Rs. %d\n", cost);

2. Relational and Logical Operators

Used for conditional checks (e.g., if statements).

Operator Name Example Result (if a=5, b=3)
== Equal to a == b 0 (false)
!= Not equal to a != b 1 (true)
> Greater than a > b 1 (true)
< Less than a < b 0 (false)
>= Greater or equal a >= b 1 (true)
<= Less or equal a <= b 0 (false)
&& Logical AND (a > 2) && (b < 4) 1 (true)
|| Logical OR (a > 10) || (b < 2) 1 (true)
! Logical NOT !(a == b) 1 (true)

Example: Check if a Daraz order is eligible for free shipping (minimum Rs. 500).

int order_total = 450;
if (order_total >= 500) {
    printf("Eligible for free shipping!\n");
} else {
    printf("Shipping cost: Rs. 50\n");
}

3. Bitwise Operators

Manipulate individual bits of integers. Critical for low-level optimizations (e.g., Khalti’s encryption, NTC’s bandwidth compression).

Operator Name Example (a=5 (0101), b=3 (0011)) Result (binary) Result (decimal)
& Bitwise AND a & b 0001 1
| Bitwise OR a | b 0111 7
^ Bitwise XOR a ^ b 0110 6
~ Bitwise NOT ~a 1010 (inverts all bits) (two’s complement)
<< Left shift a << 1 1010 10 (multiplies by 2)
>> Right shift a >> 1 0010 2 (divides by 2)

Example: Toggle the least significant bit (LSB) of a number (used in Ncell’s call logging to mark "completed" calls).

int call_status = 0b0000; // 0 (not started)
call_status ^= 0b0001;    // Toggle LSB: 0b0001 (1, started)
printf("Status: %d\n", call_status); // 1

Real-World Trace: eSewa’s Transaction Hashing eSewa uses bitwise XOR (^) to combine transaction details (amount, user ID, timestamp) into a hash for security:

unsigned int hash = amount ^ user_id ^ timestamp;
  • If amount=500, user_id=12345, timestamp=1625097600:
    • 500 ^ 12345 = 12347 (binary: 0000110000001111111)
    • 12347 ^ 1625097600 = 1625097603 (final hash).

4. Operator Precedence and Associativity

Precedence determines evaluation order. Associativity resolves ties (left-to-right for +, right-to-left for ^).

flowchart TD
    A["Parentheses ()"] --> B["Postfix: a++, a--"]
    B --> C["Unary: +, -, ~, !"]
    C --> D["Multiplicative: *, /, %"]
    D --> E["Additive: +, -"]
    E --> F["Shift: <<, >>"]
    F --> G["Relational: <, >, <=, >=, ==, !="]
    G --> H["Bitwise AND: &"]
    H --> I["Bitwise XOR: ^"]
    I --> J["Bitwise OR: |"]
    J --> K["Logical AND: &&"]
    K --> L["Logical OR: ||"]
    L --> M["Ternary: condition ? expr1 : expr2"]
    M --> N["Assignment: =, +=, etc."]

Example: Evaluate 5 + 3 * 2 >> 1:

  1. 3 * 2 = 6 (multiplication first).
  2. 5 + 6 = 11.
  3. 11 >> 1 = 5 (right shift by 1 divides by 2).

Practical Applications: Files and Number Analysis

1. Merging Two Files (eSewa-Style Transaction Logs)

Task: Merge num1.txt and num2.txt into file3.txt. Assumptions:

  • Both files contain integers, one per line.
  • num1.txt:
    10
    20
    
  • num2.txt:
    15
    25
    

Solution:

#include <stdio.h>

int main() {
    FILE *file1 = fopen("num1.txt", "r");
    FILE *file2 = fopen("num2.txt", "r");
    FILE *file3 = fopen("file3.txt", "w");

    int num;
    // Read from file1
    while (fscanf(file1, "%d", &num) != EOF) {
        fprintf(file3, "%d\n", num);
    }
    // Read from file2
    while (fscanf(file2, "%d", &num) != EOF) {
        fprintf(file3, "%d\n", num);
    }

    fclose(file1);
    fclose(file2);
    fclose(file3);
    return 0;
}

Output (file3.txt):

10
20
15
25

Real-World Tie-In:

  • eSewa’s Daily Transaction Logs:
    • num1.txt = Transactions from morning (9 AM–12 PM).
    • num2.txt = Transactions from afternoon (12 PM–5 PM).
    • file3.txt = Combined log for auditing.

2. Palindrome Check (Ncell’s Call Duration Validation)

Task: Check if a number reads the same backward (e.g., 121). Approach:

  1. Reverse the number.
  2. Compare with original.
#include <stdio.h>

int is_palindrome(int num) {
    int original = num, reversed = 0;
    while (num > 0) {
        reversed = reversed * 10 + num % 10;
        num /= 10;
    }
    return original == reversed;
}

int main() {
    int n = 121;
    if (is_palindrome(n)) {
        printf("%d is a palindrome.\n", n);
    } else {
        printf("%d is not a palindrome.\n", n);
    }
    return 0;
}

Trace for n = 121:

Step num reversed num % 10 num /= 10 reversed * 10 + ...
1 121 0 1 12 0 * 10 + 1 = 1
2 12 1 2 1 1 * 10 + 2 = 12
3 1 12 1 0 12 * 10 + 1 = 121

Output:

121 is a palindrome.

Real-World Tie-In:

  • Ncell’s Call Duration Validation:
    • Some promotional codes (e.g., 12321) are palindromes.
    • The program checks if a user-entered code is valid before applying discounts.

In the Real World

  1. Khalti’s Transaction Security:

    • Bitwise XOR (^) combines amount, user ID, and timestamp to generate a hash for fraud detection.
    • Example: For a Rs. 500 transaction by user 12345 at 1625097600:
      unsigned int hash = 500 ^ 12345 ^ 1625097600;
      // Result: 1625097603 (used to verify transaction integrity)
      
  2. NTC’s Bandwidth Compression:

    • Bitwise AND (&) masks irrelevant bits in network packets to reduce size.
    • Example: Strip the LSB (least significant bit) of a packet’s header:
      unsigned char packet_header = 0b11010011;
      unsigned char compressed = packet_header & 0b11111110; // 0b11010010
      
  3. Daraz’s Shipping Eligibility:

    • Relational operators (>=) check if an order meets the Rs. 500 threshold for free shipping.
    • Example:
      int cart_total = 480;
      if (cart_total >= 500) {
          printf("Free shipping!\n");
      } else {
          printf("Add Rs. 20 for shipping.\n");
      }
      
  4. NEPSE’s Stock Data Processing:

    • File handling (fopen, fscanf) reads daily stock prices from stock_data.txt and filters gainers (price > previous day).
    • Example:
      FILE *data = fopen("stock_data.txt", "r");
      float prev_price, current_price;
      fscanf(data, "%f", &prev_price); // Read yesterday's price
      while (fscanf(data, "%f", &current_price) != EOF) {
          if (current_price > prev_price) {
              printf("Gainer: %.2f\n", current_price);
          }
          prev_price = current_price;
      }
      

Exam Tip

  1. Memorize Ranges:

    • TU exams often ask for int, float, and char ranges. For 16-bit systems:
      • int: to .
      • float: to .
    • Trick: Remember int max is .
  2. Bitwise Operator Shortcuts:

    • a << 1 = a * 2.
    • a >> 1 = a / 2 (integer division).
    • a & 1 checks if a is odd (returns 1 if odd, 0 if even).
  3. File Handling Pitfalls:

    • Always check if fopen() returns NULL (file not found).
    • Close files with fclose() to avoid memory leaks.
    • Common Exam Question: Merge two files. Always use while (fscanf(...) != EOF) to read all data.
  4. Operator Precedence Traps:

    • 5 + 3 * 2 is 11 (not 16), because * has higher precedence.
    • Use parentheses to clarify intent: (5 + 3) * 2 = 16.
  5. Global vs. Local Variables:

    • Global: Use for constants (e.g., const float PI = 3.14;).
    • Local: Prefer for variables to avoid side effects.
    • Exam Question: "Why avoid global variables?" → Answer: unpredictable state, hard to debug.
  6. Palindrome/Prime Checks:

    • Palindrome: Reverse the number and compare.
    • Prime: Check divisibility up to .
    • Example Trace: Always show a table of variable changes (like the 121 trace above).

Summary Table: Key Operators and Their Uses

Category Operators Example Use Case Precedence Level
Arithmetic +, -, *, /, % Calculating Daraz’s shipping cost High
Relational ==, !=, >, <, etc. Checking Ncell’s call duration Medium
Logical &&, ||, ! Validating eSewa’s transaction conditions Low
Bitwise &, |, ^, ~, <<, >> Khalti’s encryption, NTC’s compression Highest
Assignment =, +=, -= Updating Pathao’s ride counter Lowest

Final Worked Example: Bank Loan Interest Calculation

Task: Calculate monthly interest for a loan using the formula: where:

  • = Principal (Rs. 100,000),
  • = Annual rate (5% = 0.05),
  • = Time in years (1).

Solution:

#include <stdio.h>

int main() {
    float principal = 100000.0;
    float rate = 0.05; // 5%
    float time = 1.0;  // 1 year
    float interest = principal * rate * time;
    printf("Monthly interest: Rs. %.2f\n", interest / 12);
    return 0;
}

Output:

Monthly interest: Rs. 416.67

Real-World Tie-In:

  • Nabil Bank’s Loan Calculator:
    • Uses float for precision (avoids integer truncation).
    • Bitwise operations could optimize interest table generation for bulk loans.

Visual Summary

classDiagram
    class DataType {
        +size: int
        +range: String
        +example: String
    }
    class Variable {
        +scope: String (local/global)
        +lifetime: String
    }
    class Operator {
        +type: String (arithmetic/relational/bitwise)
        +precedence: int
    }
    DataType "1" --> "uses" Operator : "e.g., int for counters"
    Variable "1" --> "uses" Operator : "e.g., if (x > 0)"
    Operator "1" --> "applied to" DataType : "e.g., & on int"

Based on the TU BIT syllabus for C Programming (BIT102), unit 2.

Discussion

Loading…