CACS151 C Programming

C ProgrammingUnit 316 min read

Operators & Expressions: Types, Precedence, Bitwise & Conditional Logic

Unit 3 of C Programming covers operators (arithmetic, relational, logical, bitwise, conditional, assignment, and special operators like sizeof and ?:), their precedence/associativity, and how to construct valid expressions. It explains operator overloading (via implicit conversions), side effects, and practical applica

TAKEAWAYS:

  • Operators in C are classified by utility (arithmetic, relational, logical, bitwise, etc.) and operand count (unary, binary, ternary).
  • Precedence rules dictate evaluation order; parentheses override defaults.
  • Bitwise operators (&, |, ^, ~, <<, >>) manipulate individual bits for memory efficiency (e.g., flags, compression).
  • The conditional operator (?:) is a shorthand for if-else in expressions.
  • Side effects (e.g., i++ in expressions) can lead to undefined behavior if misused.
  • sizeof returns the size in bytes of a variable or type, critical for dynamic memory allocation.


1. Introduction to Operators

Operators in C are symbols that perform operations on variables and values. They are the building blocks of expressions, which combine variables, operators, and literals to produce a result.

Classification of Operators

Operators are categorized based on their utility (function) and number of operands they require:

Category Operators Example
Arithmetic +, -, *, /, %, ++, -- a + b, x++
Relational ==, !=, >, <, >=, <= a > b
Logical &&, ||, ! a && b
Bitwise &, |, ^, ~, <<, >> a & b, x << 2
Assignment =, +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^= a += b
Conditional ?: (ternary operator) a > b ? x : y
Special sizeof, , (comma), & (address-of), * (dereference) sizeof(int), &var

2. Arithmetic Operators

Arithmetic operators perform mathematical operations. They include:

  • Binary operators: +, -, *, /, % (modulus)
  • Unary operators: ++ (increment), -- (decrement)

Example: Modulus Operator (%)

The modulus operator returns the remainder of division.

#include <stdio.h>
int main() {
    int a = 10, b = 3;
    printf("Remainder: %d\n", a % b); // Output: 1
    return 0;
}

Trace:

Step Operation Result
1 10 % 3 1

Real-world use in Nepal:

  • Ncell’s call duration billing: If a call lasts 10 minutes and the rate is 3 minutes per unit, the extra charge is calculated as 10 % 3 = 1 (extra minute).
  • NEPSE stock trading: If a trader buys 10 shares and sells 3, the remaining shares are 10 % 3 = 1.

3. Relational Operators

Relational operators compare two values and return 1 (true) or 0 (false).

Operator Meaning Example (a=5, b=3) Result
== Equal to a == b 0
!= Not equal a != b 1
> Greater than a > b 1
< Less than a < b 0
>= Greater/equal a >= b 1
<= Less/equal a <= b 0

Example: Checking Even/Odd

#include <stdio.h>
int main() {
    int num = 7;
    if (num % 2 == 0)
        printf("Even\n");
    else
        printf("Odd\n"); // Output: Odd
    return 0;
}

4. Logical Operators

Logical operators combine boolean expressions.

Operator Name Example (a=1, b=0) Result
&& Logical AND a && b 0
|| Logical OR a || b 1
! Logical NOT !a 0

Example: Multiple Conditions

#include <stdio.h>
int main() {
    int age = 20, hasLicense = 1;
    if (age >= 18 && hasLicense)
        printf("Eligible to drive\n"); // Output: Eligible
    return 0;
}

Real-world use in Nepal:

  • eSewa’s transaction approval: A payment is processed only if:
    • balance >= amount AND account is active.
    • Logical AND (&&) ensures both conditions are met.

5. Bitwise Operators

Bitwise operators manipulate individual bits of integers. They are faster than arithmetic operations and used in:

  • Memory optimization (e.g., flags in structures).
  • Cryptography (e.g., XOR operations).
  • Graphics programming (e.g., pixel manipulation).
00.751.52.253AND (&)3OR (|)3XOR (^)3NOT (~)1Left Shift (<<)2Right Shift (>>)2Bitwise operations per question (avg. in exams)
Frequency of bitwise operators in NEB exam questions (2078-2081)
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 -6 (two’s complement)
<< Left Shift a << 1 1010 10
>> Right Shift a >> 1 0010 2

Example: Setting a Flag

#include <stdio.h>
int main() {
    int flags = 0b0000; // Binary literal (C99)
    flags |= 0b0010;    // Set the 2nd bit (value = 2)
    printf("Flags: %d\n", flags); // Output: 2
    return 0;
}

Trace:

Step Operation Binary (flags) Decimal
1 flags = 0b0000 0000 0
2 `flags = 0b0010` 0010

Real-world use in Nepal:

  • Khalti’s transaction status: A transaction may have multiple flags (e.g., 0b0001 = pending, 0b0010 = failed). Using bitwise OR (|) updates the status:
    int status = 0b0001; // Pending
    status |= 0b0010;    // Now: 0b0011 (Pending + Failed)
    

6. Assignment Operators

Assignment operators assign values to variables. The compound assignment operators (+=, -=, etc.) combine an operation with assignment.

Operator Example Equivalent To
= a = b a = b
+= a += b a = a + b
-= a -= b a = a - b
*= a *= b a = a * b
/= a /= b a = a / b
%= a %= b a = a % b
<<= a <<= b a = a << b
>>= a >>= b a = a >> b
&= a &= b a = a & b
|= a |= b a = a | b
^= a ^= b a = a ^ b

Example: Compound Assignment

#include <stdio.h>
int main() {
    int x = 5;
    x += 3; // Equivalent to x = x + 3
    printf("x = %d\n", x); // Output: 8
    return 0;
}

7. Conditional (Ternary) Operator (?:)

The ternary operator is a shorthand for if-else in expressions. Syntax:

condition ? expression1 : expression2;

Example: Maximum of Two Numbers

#include <stdio.h>
int main() {
    int a = 10, b = 20;
    int max = (a > b) ? a : b;
    printf("Max: %d\n", max); // Output: 20
    return 0;
}

Real-world use in Nepal:

  • Pathao’s fare calculation: If distance <= 2km, fare = 100 NPR; else, fare = 150 NPR.
    int fare = (distance <= 2) ? 100 : 150;
    

8. Special Operators

(a) sizeof Operator

Returns the size in bytes of a variable or data type.

#include <stdio.h>
int main() {
    printf("Size of int: %zu bytes\n", sizeof(int)); // Typically 4
    printf("Size of float: %zu bytes\n", sizeof(float)); // Typically 4
    return 0;
}

Real-world use in Nepal:

  • Bank loan calculations: If a bank stores 10,000 customer records, and each record is sizeof(struct Customer) = 100 bytes, total memory needed is 10,000 * 100 = 1,000,000 bytes.

(b) Comma Operator (,)

Evaluates expressions left to right and returns the last value.

#include <stdio.h>
int main() {
    int a = (5, 10, 15); // Returns 15
    printf("a = %d\n", a); // Output: 15
    return 0;
}

9. Operator Precedence and Associativity

Operators have precedence (evaluation order) and associativity (left-to-right or right-to-left).

Precedence (High to Low) Operators Associativity
1 (), [], ., -> Left to Right
2 !, ~, ++, --, sizeof, &, * Right to Left
3 *, /, % Left to Right
4 +, - Left to Right
5 <<, >> Left to Right
6 <, <=, >, >= Left to Right
7 ==, != Left to Right
8 & Left to Right
9 ^ Left to Right
10 | Left to Right
11 && Left to Right
12 || Left to Right
13 ?: (ternary) Right to Left
14 =, +=, -=, etc. Right to Left
15 , Left to Right

Example: Precedence in Action

#include <stdio.h>
int main() {
    int a = 5, b = 3, c = 2;
    int result = a + b * c; // Multiplication first (6), then addition (11)
    printf("Result: %d\n", result); // Output: 11
    return 0;
}

Mermaid Diagram: Operator Precedence Flow

0123456789101112b * c (3 * 2 = 6)a + 6 (5 + 6 = 11)
Step-by-step evaluation of `a + b * c` (a=5, b=3, c=2) showing precedence

10. Side Effects and Undefined Behavior

  • Side effects occur when an operator modifies a variable (e.g., i++ in x = i++ + 1).
  • Undefined behavior happens when side effects interfere with evaluation order (e.g., modifying a variable twice in one expression).

Bad Example (Undefined Behavior):

int x = 5;
int y = x++ + ++x; // Undefined! (x is modified twice)

Correct Way:

int x = 5;
int y = x + 1; // Safe
x++;

11. Swapping Without a Temporary Variable

A common interview question: Swap two numbers without a third variable using arithmetic or bitwise operations.

100201
Before swap (a=10, b=20)

Method 1: Arithmetic (Using + and -)

#include <stdio.h>
int main() {
    int a = 5, b = 10;
    printf("Before swap: a = %d, b = %d\n", a, b);
    a = a + b; // 15
    b = a - b; // 5
    a = a - b; // 10
    printf("After swap: a = %d, b = %d\n", a, b); // Output: 10, 5
    return 0;
}

Trace:

Step Operation a b
1 a = a + b 15 10
2 b = a - b 15 5
3 a = a - b 10 5

Real-world use in Nepal:

  • Daraz’s order processing: If two orders have IDs 5 and 10, swapping them without a temp variable avoids extra memory usage in high-throughput systems.

Method 2: Bitwise XOR (No Arithmetic Overflow)

#include <stdio.h>
int main() {
    int a = 5, b = 10;
    printf("Before swap: a = %d, b = %d\n", a, b);
    a = a ^ b; // 15 (0101 ^ 1010 = 1111)
    b = a ^ b; // 5  (1111 ^ 1010 = 0101)
    a = a ^ b; // 10 (1111 ^ 0101 = 1010)
    printf("After swap: a = %d, b = %d\n", a, b); // Output: 10, 5
    return 0;
}

Trace:

Step Operation a (Binary) b (Binary)
1 a = a ^ b 1111 (15) 1010 (10)
2 b = a ^ b 1111 (15) 0101 (5)
3 a = a ^ b 1010 (10) 0101 (5)

12. Evaluating Complex Expressions

Problem: Calculate for , . Solution:

#include <stdio.h>
#include <math.h>
int main() {
    int x = 3, y = 4;
    double result = 5 * x * sqrt(y * y) + 5;
    printf("Result: %.2f\n", result); // Output: 65.00
    return 0;
}

Trace:

Step Operation Value
1 y * y 16
2 sqrt(16) 4.0
3 5 * x * 4.0 60.0
4 60.0 + 5 65.0

Real-world use in Nepal:

  • NTC’s electricity billing: If a consumer uses units and the rate is (where is demand factor), the bill is calculated similarly.

In the Real World

  1. Khalti’s Transaction Flags

    • Idea Used: Bitwise operators (&, |, ^).
    • How? Khalti uses bitmasking to store multiple transaction states (e.g., 0b0001 = pending, 0b0010 = failed). A single int can represent multiple flags efficiently.
    • Example:
      int status = 0b0001; // Pending
      status |= 0b0010;    // Now: 0b0011 (Pending + Failed)
      
  2. Ncell’s Call Duration Calculation

    • Idea Used: Modulus operator (%).
    • How? If a call lasts 10 minutes and billing is per 3-minute unit, the extra charge is 10 % 3 = 1 minute.
    • Example:
      int minutes = 10, unit = 3;
      int extra = minutes % unit; // 1
      
  3. Pathao’s Dynamic Fare Adjustment

    • Idea Used: Ternary operator (?:).
    • How? If distance <= 2km, fare = 100 NPR; else, fare = 150 NPR.
    • Example:
      int fare = (distance <= 2) ? 100 : 150;
      
  4. Bank Loan Interest Calculation

    • Idea Used: Arithmetic operators (*, /).
    • How? Simple interest is calculated as: where = principal, = rate, = time.
    • Example:
      float interest = (principal * rate * time) / 100;
      

Exam Tip

  1. Operator Precedence is Critical

    • Always use parentheses to clarify intent. For example:
      • Correct: (a + b) * c
      • Ambiguous: a + b * c (multiplication has higher precedence).
    • Exam Pitfall: Forgetting precedence leads to wrong answers. Example:
      int x = 2 + 3 * 4; // x = 14 (not 20)
      
  2. Bitwise Operators are High-Weightage

    • Questions often ask for bitwise AND/OR/XOR operations or flag manipulation.
    • Example Question: "Given a = 5 (0101) and b = 3 (0011), compute a & b, a | b, and a ^ b."
  3. Swapping Without Temp Variable

    • A common 5-mark question. Know both arithmetic and bitwise methods.
    • Exam Tip: Show binary traces for bitwise swapping to get full marks.
  4. sizeof Operator

    • Often tested with structures or arrays. Example: "Write a program to find the size of an array of 10 integers."
      int arr[10];
      printf("Size: %zu bytes\n", sizeof(arr)); // Typically 40 (10 * 4)
      
  5. Side Effects and Undefined Behavior

    • Avoid modifying a variable twice in one expression (e.g., x = ++x + 1).
    • Exam Tip: If asked to explain undefined behavior, cite:
      • Modifying a variable multiple times in one expression.
      • Unsequenced modifications (e.g., i++ and i-- in the same statement).
  6. Ternary Operator Shortcuts

    • Replace if-else with ?: where possible. Example:
      // Instead of:
      if (x > y) max = x; else max = y;
      // Use:
      int max = (x > y) ? x : y;
      
  7. Real-World Applications

    • Expect 1-2 questions linking operators to real-world scenarios (e.g., billing, flags, swapping).
    • Example: "How would you use bitwise operators to optimize memory in a system storing user permissions?"

Based on the TU BCA syllabus for C Programming (CACS151), unit 3.

Discussion

Loading…