Computer Systems Fundamentals


Demonstrate C bitwise operations
#include <stdio.h>

void print_bits_hex(char *description, short n);
void print_bits(short value);
int get_nth_bit(short value, int n);

int main(void) {
    short a = 0;
    printf("Enter a: ");
    scanf("%hd", &a);
    short b = 0;
    printf("Enter b: ");
    scanf("%hd", &b);
    printf("Enter c: ");
    int c = 0;
    scanf("%d", &c);
    print_bits_hex("     a = ", a);
    print_bits_hex("     b = ", b);
    print_bits_hex("    ~a = ", ~a);
    print_bits_hex(" a & b = ", a & b);
    print_bits_hex(" a | b = ", a | b);
    print_bits_hex(" a ^ b = ", a ^ b);
    print_bits_hex("a >> c = ", a >> c);
    print_bits_hex("a << c = ", a << c);
    return 0;
}

// print description then binary, hex and decimal representation of value
void print_bits_hex(char *description, short value) {
    printf("%s", description);
    print_bits(value);
    printf(" = 0x%04x = %d\n", value & 0xFFFF, value);
}

// print the binary representation of a value
void print_bits(short value) {
    // sizeof returns size in bytes and 1 byte == 8 bits
    int how_many_bits = 8 * (sizeof value);
    for (int i = how_many_bits - 1; i >= 0; i--) {
        int bit = get_nth_bit(value, i);
        printf("%d", bit);
    }
}

// extract the nth bit from a value
int get_nth_bit(short value, int n) {
    return (value >> n) & 1;
}


Print hexadecimal directly (without using printf) usign bitwise opeators to extract digits
#include <stdio.h>
#include <stdio.h>

void print_hex(int n);

int main(void) {
    int a = 0;
    printf("Enter an int: ");
    scanf("%d", &a);
    printf("%d = 0x", a);
    print_hex(a);
    printf("\n");
    return 0;
}

void print_hex(int n) {
    int which_digit = 2 * (sizeof n);
    while (which_digit > 0) {
        which_digit--;
        int digit = (n >> (4 * which_digit)) & 0xF;
        int ascii = "0123456789ABCDEF"[digit];
        putchar(ascii);
    }
}
#include <stdio.h>

// Andrew Taylor - andrewt@unsw.edu.au
// 16/9/2019
// Represent a small set of possible values using bits


#define FIRE_TYPE      0x0001
#define FIGHTING_TYPE  0x0002
#define WATER_TYPE     0x0004
#define FLYING_TYPE    0x0008
#define POISON_TYPE    0x0010
#define ELECTRIC_TYPE  0x0020
#define GROUND_TYPE    0x0040
#define PSYCHIC_TYPE   0x0080
#define ROCK_TYPE      0x0100
#define ICE_TYPE       0x0200
#define BUG_TYPE       0x0400
#define DRAGON_TYPE    0x0800
#define GHOST_TYPE     0x1000
#define DARK_TYPE      0x2000
#define STEEL_TYPE     0x4000
#define FAIRY_TYPE     0x8000

int main(void) {
    // give our pokemon 3 types
    int pokemon_type = BUG_TYPE | POISON_TYPE | FAIRY_TYPE;

    printf("0x%04xd\n", pokemon_type);

    if (pokemon_type & POISON_TYPE) {
        printf("Danger poisonous\n"); // prints
    }

    if (pokemon_type & GHOST_TYPE) {
        printf("Scary\n"); // does not print
    }
}

Respresent set of small non-negative integers using bit-operations
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

typedef uint64_t set;

#define MAX_SET_MEMBER ((int)(8 * sizeof(set) - 1))
#define EMPTY_SET 0

set set_add(int x, set a);
set set_union(set a, set b);
set set_intersection(set a, set b);
set set_member(int x, set a);
int set_cardinality(set a);
set set_read(char *prompt);
void set_print(char *description, set a);

void print_bits_hex(char *description, set n);
void print_bits(set value);
int get_nth_bit(set value, int n);

int main(void) {
    printf("Set members can be 0-%d, negative number to finish\n", MAX_SET_MEMBER);
    set a = set_read("Enter set a: ");
    set b = set_read("Enter set b: ");
    print_bits_hex("a = ", a);
    print_bits_hex("b = ", b);
    set_print("a = ", a);
    set_print("b = ", b);
    set_print("a union b = ", set_union(a, b));
    set_print("a intersection b = ", set_intersection(a, b));
    printf("cardinality(a) = %d\n", set_cardinality(a));
    printf("is_member(42, a) = %d\n", (int)set_member(42, a));
    return 0;
}

set set_add(int x, set a) {
    return a | ((set)1 << x);
}

set set_union(set a, set b) {
    return a | b;
}

set set_intersection(set a, set b) {
    return a & b;
}

// return a non-zero value iff x is a member of a
set set_member(int x, set a) {
    assert(x >= 0 && x < MAX_SET_MEMBER);
    return a & ((set)1 << x);
}

// return size of set
int set_cardinality(set a) {
    int n_members = 0;
    while (a != 0) {
        n_members += a & 1;
        a >>= 1;
    }
    return n_members;
}

set set_read(char *prompt) {
    printf("%s", prompt);
    set a = EMPTY_SET;
    int x;
    while (scanf("%d", &x) == 1 && x >= 0) {
        a = set_add(x, a);
    }
    return a;
}

// print out member of the set in increasing order
// for example {5,11,56}
void set_print(char *description, set a) {
    printf("%s", description);
    printf("{");
    int n_printed = 0;
    for (int i = 0; i < MAX_SET_MEMBER; i++) {
        if (set_member(i, a)) {
            if (n_printed > 0) {
                printf(",");
            }
            printf("%d", i);
            n_printed++;
        }
    }
    printf("}\n");
}

// print description then binary, hex and decimal representation of value
void print_bits_hex(char *description, set value) {
    printf("%s", description);
    print_bits(value);
    printf(" = 0x%08lx = %ld\n", value, value);
}

// print the binary representation of a value
void print_bits(set value) {
    // sizeof returns size in bytes and 1 byte == 8 bits
    int how_many_bits = 8 * (sizeof value);
    for (int i = how_many_bits - 1; i >= 0; i--) {
        int bit = get_nth_bit(value, i);
        printf("%d", bit);
    }
}

// extract the nth bit from a value
int get_nth_bit(set value, int n) {
    return (value >> n) & 1;
}
#include <stdio.h>
#include <stdint.h>

int main(void) {
    // int16_t is a signed type (-32768..32767)
    // all operations below are defined for a signed type
    int16_t i;

    i = -1;
    i = i >> 1; // undefined -  shift of a negative value
    printf("%d\n", i);
    i = -1;
    i = i << 1; // undefined -  shift of a negative value
    printf("%d\n", i);
    i = 32767;
    i = i << 1; // undefined -  left shift produces a negative value

    uint64_t j;
    j = 1 << 33; // undefined - 1 type is int
    j = ((uint64_t)1) << 33; // ok
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//
// copy stdin to stdout xor each byte with value supplied on STDIN
//
//
// Try
// $ dcc xor.c -o xor
// $ <xor.c xor 42
// $ <xor.c xor 42|xor 42
//

int main(int argc, char *argv[]) {
    assert(argc == 2);
    char key = strtol(argv[1], NULL, 0);
    int c;
    while ((c = getchar()) != EOF) {
        int xor_c = c ^ key;
        putchar(xor_c);
    }
    return 0;
}