Skip to content

csapp/bits.c ​

配套源码,运行方法见同目录 README。返回实验总览。

c
/* Original exercises: defined C11 operations, not restricted Data Lab answers. */
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

static unsigned population(uint32_t value) {
    unsigned count = 0;
    while (value) {
        value &= value - UINT32_C(1);
        ++count;
    }
    return count;
}

static uint32_t rotate_left(uint32_t value, unsigned amount) {
    amount %= 32;
    if (amount == 0) return value; /* A shift by 32 would be undefined. */
    return (value << amount) | (value >> (32 - amount));
}

static bool add_i32(int32_t a, int32_t b, int32_t *out) {
    int64_t wide = (int64_t)a + b;
    if (wide < INT32_MIN || wide > INT32_MAX) return false;
    *out = (int32_t)wide;
    return true;
}

int main(void) {
    assert(CHAR_BIT == 8);
    assert(population(0) == 0);
    assert(population(UINT32_MAX) == 32);
    assert(population(UINT32_C(0x80000001)) == 2);
    assert(rotate_left(UINT32_C(0x80000001), 1) == 3);
    assert(rotate_left(UINT32_C(0x80000001), 0) == UINT32_C(0x80000001));
    assert(rotate_left(UINT32_C(0x80000001), 32) == UINT32_C(0x80000001));
    int32_t result = 99;
    assert(!add_i32(INT32_MAX, 1, &result) && result == 99);
    assert(!add_i32(INT32_MIN, -1, &result) && result == 99);
    assert(add_i32(INT32_MIN, INT32_MAX, &result) && result == -1);
    assert(add_i32(15, -7, &result) && result == 8);
    uint32_t word = UINT32_C(0x12345678);
    unsigned char bytes[sizeof word];
    memcpy(bytes, &word, sizeof bytes);
    printf("memory bytes: %02x %02x %02x %02x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
    printf("wrap: %" PRIu32 "\n", UINT32_MAX + UINT32_C(1));
    puts("bits: boundary checks passed");
    return 0;
}