深入理解计算机操作系统第二章家庭作业

深入理解计算机系统第二章家庭作业(2.91-2.96) /***********2.91*************/ /*Compute |f|.   If f is NaN, then return f.*/ float_bits float_absval(float_bits f) { unsigned exp = (f >> 23) & 0xFF; unsigned frac = f &0x7FFFFF; if(exp == 阅读详情

2.55 编译运行下列代码,并且确定机器字节顺序。

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {  // size_t == unsigned 8bit integer
    size_t i;
    for (i = 0; i < len; ++i) {
        printf("%.2x ", start[i]);
    }
    printf("\n");
}

void show_int(int x) {
    show_bytes((byte_pointer) &x, sizeof(int));
}

void show_float(float x) {
    show_bytes((byte_pointer) &x, sizeof(float));
}

void show_pointer(void *x) {
    printf("x's address value is [%p] \n", x);
    show_bytes((byte_pointer) &x, sizeof(void *));
}

void test_show_bytes(int val) {
    int ival = val;
    float fval = (float) ival;
    int *pval = &ival;
    show_int(ival);
    show_float(fval);
    show_pointer(pval);
}

int main(void) {
    int test_number = 1234;
    test_show_bytes(test_number); // 1234 == 100 1101 0010 == 00 00 04 d2(大端) == d2 04 00 00 (小端)
    return 0;
}

我的机器是小端顺序,intel 基本上都是小端。

为什么 byte_pointer 使用 unsigned char * (而不是 char *)?

#include <stdio.h>

int main()
{
    char c = 129;// 1000 0001      11111111 1000 0001
    char unsigned uc = 129;
    printf("%d\n", c);
    printf("%x\n", c);
    printf("%d\n", uc);
    printf("%x\n", uc);
    return 1;
}

/* 输出
-127
ffffff81
129
81
 * /

2.56 试着用不同示例值运行上面的代码。

同上。

2.57 同上面一样去编写程序 show_short, show_long, show_double 并运行。

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {
    size_t i;
    for (i = 0; i < len; ++i) {
        printf("%.2x ", start[i]);
    }
    printf("\n\n");
}

void show_short(short x) {
    show_bytes((byte_pointer) &x, sizeof(short));
}

void show_long(long x) {
    show_bytes((byte_pointer) &x, sizeof(long));
}

void show_double(double x) {
    show_bytes((byte_pointer) &x, sizeof(double));
}

void test_show_bytes(int ival) {
    short sval = (short) ival;
    long lval = (long) ival;
    double dval = (double) ival;
    show_short(sval);
    show_long(lval);
    show_double(dval);
}

int main(void) {
    test_show_bytes(0x12345678);
    return 0;
}
78 56

78 56 34 12

00 00 00 78 56 34 b2 41

2.58 编写 is_little_endian 函数判断大端还是小端,返回 0 和 1。

#include <stdio.h>

int main() {
    int i = 65538; // 00000000 00000001 00000000 00000010
    unsigned char *j = (unsigned char *) &i;

    if (*j == 2) {
        printf("1");
        return 1;   // little endian
    }
    printf("0");
    return 0;
}

2.59 编写程序返回 x 的最低有效字节,和 y 中剩下的字节。

#include <stdio.h>

int main() {
    int i = 65538; // 0x10002
    int j = 12345; // 0x3039
    printf("%x", (i & 0xff) | (j & ~0xff));
    return 1;
}

2.60 将字节从 0 开始编号,写出函数实现将参数 x 的字节 i 被替换成字节 b。

#include <stdio.h>
#include <assert.h>

int replace_byte(unsigned x, unsigned char i, unsigned char b) {
    return ((-1 - (0xff << (i  << 3))) & x) | (b<<(i<<3));
}

int main() {
    unsigned rep_0 = replace_byte(0x12345678, 0, 0xAB);
    unsigned rep_3 = replace_byte(0x12345678, 3, 0xAB);

    assert(rep_0 == 0x123456AB);
    assert(rep_3 == 0xAB345678);
    return 1;
}

2.61

#include <stdio.h>

int get_msb(int x) {
    return ((!x)
            | (!(~x))
            | (!((~(x & 0xff)) & 0xff)) 
            | (!(x >> ((sizeof(x) - 1)<<3 ))));  
}

int main() {
    printf("%d", get_msb(0xff));
    printf("%d", get_msb(0));
    printf("%d", get_msb(0x11ff));
    printf("%d", get_msb(0xff00));
    printf("%d", get_msb(0xffff00));
    return 1;
}

2.62

#include <stdio.h>

int main() {
    int a = -1;
    int res = !(~(a >> 1));
    printf("%d", res);
    return 1;
}

2.63

#include <stdio.h>

unsigned srl(unsigned x, int k) {
    unsigned xsra = (int) x >> k;
    return (~(-1 << ((sizeof(int) << 3) - k))) & xsra;
}

int main() {
    unsigned a = 0xffffffff;
    unsigned v = srl(a, 3);
    printf("%x", v);
    return 1;
}
#include <stdio.h>

unsigned sra(int x, int k) {
    unsigned xsrl = (unsigned) x >> k;
    int bits = sizeof(int) << 3;
    return (-!!(1 << (bits - 1) & x)) << (bits - k) | xsrl;
}

int main() {
    unsigned a = 0xffffffff;
    unsigned v = sra(a, 15);
    printf("%x", v);
    return 1;
}

2.64

#include <stdio.h>

int any_odd_one(unsigned x) {
    return !!(x & 0xaaaaaaaa);
}

int main() {
    unsigned a = 0x5;
    int b = any_odd_one(a);
    printf("%d", b);
    return 1;
}

2.55

#include <stdio.h>
#include <assert.h>

int odd_ones(unsigned x) {
    x ^= x >> 16;
    x ^= x >> 8;
    x ^= x >> 4;
    x ^= x >> 2;
    x ^= x >> 1;
    x &= 0x1;
    return x;
}

int main(int argc, char *argv[]) {
    assert(odd_ones(0x10101011));
    assert(!odd_ones(0x01010101));
    return 0;
}

2.66

#include <stdio.h>
#include <assert.h>

unsigned left_most_one(unsigned x) {
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    return (x + 1) >> 1;
}

int main() {
    assert(left_most_one(0xff00) == 0x8000);
    assert(left_most_one(0x6600) == 0x4000);
    return 1;
}

2.67

  1. c11 标准指出:如果右移的位数为负数,或者左移的位数大于等于数值宽度,则结果在标准中未定义。
  2. 和 3.
#include <stdio.h>
#include <assert.h>

int int_size_is_32() {
    int set_msb = 1 << 31;
    int beyond_msb = set_msb << 1;

    return set_msb && !beyond_msb;
}

int int_size_is_32_for_16bit() {
    int set_msb = 1 << 15 << 15 << 1;
    int beyond_msb = set_msb << 1;

    return set_msb && !beyond_msb;
}

int main(int argc, char *argv[]) {
    assert(int_size_is_32());
    assert(int_size_is_32_for_16bit());
    return 0;
}

2.68

#include <stdio.h>
#include <assert.h>

int lower_one_mask(int n) {
    return ~(-1 << n);
}

int main() {
    assert(lower_one_mask(6) == 0x3f);
    assert(lower_one_mask(17) == 0x1ffff);
    return 1;
}

2.69

#include <stdio.h>
#include <assert.h>

unsigned rotate_left(unsigned x, int n) {
    return (x << n) | (x >> ((sizeof(x) << 3) - n));
// 这么写不对,考虑 n = w 的情况,左移位数等于数值宽度,在 c 标准中未规范
// return (x << (n-1)<<1) | (x >> ((sizeof(x) << 3) - n));
}

int main() {
    assert(rotate_left(0x12345678, 4) == 0x23456781);
    assert(rotate_left(0x12345678, 20) == 0x67812345);
    assert(rotate_left(0x12345678, 0) == 0x12345678);
    return 1;
}

2.70

#include <stdio.h>
#include <assert.h>

int fits_bits(int x, int n) {
    int spare = (sizeof(int) << 3) - n;
    return x == (x << spare >> spare);
}

int main(int argc, char *argv[]) {
    assert(!fits_bits(0xFF, 8));
    assert(!fits_bits(~0xFF, 8));

    assert(fits_bits(0b0010, 3));
    assert(!fits_bits(0b1010, 3));
    assert(!fits_bits(0b0110, 3));

    assert(fits_bits(~0b11, 3));
    assert(!fits_bits(~0b01000011, 3));
    assert(!fits_bits(~0b111, 3));
    return 0;
}

2.71

书本答案未曾考虑到算术右移。

#include <stdio.h>
#include <assert.h>

typedef unsigned packed_t;

int xbyte(packed_t word, int byteNum) {
    packed_t a = (word >> (bytenum << 3)) & 0xff;
    return -(a >> 7) << 8 | a;
}

int main(int argc, char *argv[]) {
    assert(0x0000000f == xbyte(0x00000f00, 1));
    assert(0xffffffff == xbyte(0x0000ff00, 1));
    assert(xbyte(0xAABBCCDD, 1) == 0xFFFFFFCC);
    assert(xbyte(0x00112233, 2) == 0x11);
    return 0;
}

2.72

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

void copy_int(int val, void *buf, int maxbytes) {
    if (maxbytes >= (int) sizeof(val)) {
        memcpy(buf, (void *) &val, sizeof(val));
    }
}

int main() {
    int a = 0x12345678;
    unsigned maxbytes = sizeof(int);
    void *buf = malloc(maxbytes);

    copy_int(a, buf, maxbytes);
    assert(0x12345678 == *(int *) buf);
    int b = 0xffffffff;
    copy_int(b, buf, 0);
    assert(0x12345678 == *(int *) buf);
    assert(0xffffffff != *(int *) buf);

    return 1;
}

2.73

#include <stdio.h>
#include <assert.h>
#include <limits.h>

int saturating_add(int x, int y) {
    int sum = x + y;
    int min = INT_MIN;
    int neg_over = (min & x) && (min & y) && !(min & sum);
    int poa_over = !(min & x) && !(min & y) && (min & sum);
    (negOver && (sum = INT_MIN)) || (posOver && (sum = INT_MAX));
    return sum;
}

int main(int argc, char *argv[]) {
    assert(INT_MAX == saturating_add(INT_MAX, 0x1234));
    assert(INT_MIN == saturating_add(INT_MIN, -0x1234));
    assert(0x11 + 0x22 == saturating_add(0x11, 0x22));
    return 0;
}

2.74

#include <stdio.h>
#include <assert.h>
#include <limits.h>

int tsub_ok(int x, int y) {
    int a = (!!(INT_MIN & x)) && (y == -y);
    int b = !((!!(INT_MIN & x)) ^ (!!(INT_MIN & y)));
    return a || b;
}

int main(int argc, char *argv[]) {
    assert(!tsub_ok(1, INT_MIN));
    assert(tsub_ok(1, 3));
    assert(tsub_ok(-1, INT_MIN));
    assert(!tsub_ok(0x00, INT_MIN));
    assert(tsub_ok(0x00, 0x00));
    return 0;
}

2.75

#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <limits.h>

int signed_high_prod(int x, int y) {
    int64_t mul = (int64_t) x * y;
    return mul >> 32;
}

unsigned unsigned_high_prod(unsigned x, unsigned y) {
    int sig_x = x >> 31;
    int sig_y = y >> 31;
    int signed_prod = signed_high_prod(x, y);
    return signed_prod + x * sig_y + y * sig_x;
}

unsigned another_unsigned_high_prod(unsigned x, unsigned y) {
    uint64_t mul = (uint64_t) x * y;
    return mul >> 32;
}

int main(int argc, char *argv[]) {
    unsigned x = 0x12345678;
    unsigned y = 0xffffffff;
    assert(another_unsigned_high_prod(x, y) == unsigned_high_prod(x, y));
    assert(signed_high_prod(x, y) != unsigned_high_prod(x, y));
    return 0;
}

2.76

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

void *another_calloc(size_t nmemb, size_t size) {
    if (nmemb == 0 || size == 0) {
        return NULL;
    }

    size_t buf_size = nmemb * size;
    if (nmemb == buf_size / size) {
        void *ptr = malloc(buf_size);
        memset(ptr, 0, buf_size);
        return ptr;
    }
    return NULL;
}

int main(int argc, char *argv[]) {
    void *p;
    p = another_calloc(0x1234, 2);
    assert(p != NULL);
    free(p);

    p = another_calloc(SIZE_MAX, 2);
    assert(p == NULL);
    free(p);
    return 0;
}

2.77

#include <stdio.h>
#include <assert.h>

int A(int x) {
    return (x << 4) + x;
}

int B(int x) {
    return x - (x << 3);
}

int C(int x) {
    return (x << 6) - (x << 2);
}

int D(int x) {
    return (x << 4) - (x << 7);
}

int main(int argc, char *argv[]) {
    int x = 0x87654321;
    assert(A(x) == 17 * x);
    assert(B(x) == -7 * x);
    assert(C(x) == 60 * x);
    assert(D(x) == -112 * x);
    return 0;
}

2.78

#include <stdio.h>
#include <assert.h>
#include <limits.h>

int divide_power2(int x, int k) {
    int is_neg = x & INT_MIN;
    (is_neg && (x = x + (1 << k) - 1));
    return x >> k;
}

int main(int argc, char* argv[]) {
    int x = 0x80000007;
    assert(divide_power2(x, 1) == x / 2);
    assert(divide_power2(x, 2) == x / 4);
    return 0;
}

2.79

#include <stdio.h>
#include <limits.h>
#include <assert.h>

int div(int x, int k) {
    int is_neg = x & INT_MIN;
    is_neg && (x = x + (1 << k) - 1);
    return x >> k;
}

int mul3div4(int x) {
    return div((x << 2) - x, 2);
}

int main(int argc, char *argv[]) {
    int x = 0x87654321;
    assert(mul3div4(x) == x * 3 / 4);
    return 0;
}

2.80

#include <stdio.h>
#include <limits.h>
#include <assert.h>

int threeforths(int x) {
    int is_neg = x & INT_MIN;
    int f = x & ~0x3;
    int l = x & 0x3;

    int fd4 = f >> 2;
    int fd4m3 = (fd4 << 1) + fd4;

    int lm3 = (l << 1) + l;
    int bias = (1 << 2) - 1;
    (is_neg && (lm3 += bias));
    int lm3d4 = lm3 >> 2;

    return fd4m3 + lm3d4;
}

int main(int argc, char *argv[]) {
    assert(threeforths(0) == 0);
    assert(threeforths(1) == 0);
    assert(threeforths(2) == 1);
    assert(threeforths(3) == 2);
    assert(threeforths(8) == 6);
    assert(threeforths(9) == 6);
    assert(threeforths(10) == 7);
    assert(threeforths(11) == 8);
    assert(threeforths(12) == 9);

    assert(threeforths(-8) == -6);
    assert(threeforths(-9) == -6);
    assert(threeforths(-10) == -7);
    assert(threeforths(-11) == -8);
    assert(threeforths(-12) == -9);
    return 0;
}

2.81

-1 << k

~(-1 << k) << j

2.82

错。 x 是 INT_MIN
对。
对。
对。
对。

2.83

#include <stdio.h>
#include <limits.h>
#include <assert.h>

int threeforths(int x) {
    int is_neg = x & INT_MIN;
    int f = x & ~0x3;
    int l = x & 0x3;

    int fd4 = f >> 2;
    int fd4m3 = (fd4 << 1) + fd4;

    int lm3 = (l << 1) + l;
    int bias = (1 << 2) - 1;
    (is_neg && (lm3 += bias));
    int lm3d4 = lm3 >> 2;

    return fd4m3 + lm3d4;
}

int main(int argc, char *argv[]) {
    assert(threeforths(0) == 0);
    assert(threeforths(1) == 0);
    assert(threeforths(2) == 1);
    assert(threeforths(3) == 2);
    assert(threeforths(8) == 6);
    assert(threeforths(9) == 6);
    assert(threeforths(10) == 7);
    assert(threeforths(11) == 8);
    assert(threeforths(12) == 9);

    assert(threeforths(-8) == -6);
    assert(threeforths(-9) == -6);
    assert(threeforths(-10) == -7);
    assert(threeforths(-11) == -8);
    assert(threeforths(-12) == -9);
    return 0;
}

2.83

A.
n = 0.yyyyy...
n << k = y.yyyyy... = Y + n
n << k - n = Y
n = Y/(2^k - 1)

B.

(a).
y = 101, Y = 5, k = 3
n = 5/7

(b).
y = 0110, Y = 6, k = 4
n = 2/5

(c).
y = 010011, Y = 19, k = 6
n = 19/63

2.84

#include <stdio.h>
#include <assert.h>

unsigned f2u(float x) {
    return *(unsigned *) &x;
}

int float_le(float x, float y) {
    unsigned ux = f2u(x);
    unsigned uy = f2u(y);

    unsigned sx = ux >> 31;
    unsigned sy = uy >> 31;

    return (ux << 1 == 0 && uy << 1 == 0) || /* both zeros */
           (sx && !sy) ||                         /* x < 0, y >= 0 or x <= 0, y > 0 */
           (!sx && ux <= uy) ||            /* x > 0, y >= 0 or x >= 0, y > 0 */
           (sx && ux >= uy);                /* x < 0, y <= 0 or x <= 0, y < 0 */
}

int main(int argc, char *argv[]) {
    assert(float_le(-0, +0));
    assert(float_le(+0, -0));
    assert(float_le(0, 3));
    assert(float_le(-4, -0));
    assert(float_le(-4, 4));
    return 0;
}

2.85

// 注意题目中并没有说有符号位
bias = 2^(k - 1) - 1
V = 2^E * M

a. 
7.0 = 0b111.000...
M = 0b1.11
f = 0b0.11
E = 2
e = bias + E
V = 7.0
结果是 10...1 110...

b.
bias+n 1...

c.
1...101 0...

2.86

0 0...(15) 0 0...(62)1	2^(1-bias-63)
0 0...(14)1 1 0....(63)	2^(1-bias)
0 1...(14)0 1 1...(63)	2^bias * (2-2^-63)

2.87

描述HexMEVD
-00x80000-14-0-0.0
>2 least0x40011025/102411025/5122.00195312
5120x600019512512.0
bigest denormalized0x03FF1023/1024-141023/(2^24)6.09755516e-5
-∞0xFC00---∞-∞
ox3BB00x3BB0123/64-1123/1280.9609375

2.88

A bitA valueB bitB value
1 01110 001-9/161 0110 0010-9/16
0 10110 10113*2^40 1110 101013*2^4
1 00111 110-7/2^101 0000 0111-7/2^10
0 00000 1015/2^170 0000 00011/2^10
1 11011 000-2^121 1110 1111-31*2^3
0 11000 1003*2^80 1111 0000+oo

2.89

#include <stdio.h>
#include <assert.h>
#include <limits.h>

/*
 * most important thing is that all double number come from ints
 */

/* right */
int A(int x, double dx) {
    return (float) x == (float) dx;
}

/* wrong when y is INT_MIN */
int B(int x, double dx, int y, double dy) {
    return dx - dy == (double) (x - y);
}

/* right */
int C(double dx, double dy, double dz) {
    return (dx + dy) + dz == dx + (dy + dz);
}

/*
 * wrong
 *
 * FIXME I don't know what conditions cause false
 */
int D(double dx, double dy, double dz) {
    return (dx * dy) * dz == dx * (dy * dz);
}

/* wrong when dx != 0 and dz == 0 */
int E(double dx, double dz) {
    return dx / dx == dz / dz;
}

int main(int argc, char *argv[]) {

    int x = 111;
    int y = 222;
    int z = 333;
    double dx = (double) x;
    double dy = (double) y;
    double dz = (double) z;

    printf("%x %x %x\n", x, y, z);

    assert(A(x, dx));   // double 可以表示所有32位整数
    assert(!B(0, (double) (int) 0, INT_MIN, (double) (int) INT_MIN));    // 溢出问题
    assert(C(dx, dy, dz));    // double 可以表示所有32位整数
    assert(!D((double) (int) 0x64e73387, (double) (int) 0xd31cb264, (double) (int) 0xd22f1fcd)); // double 并不能表示所有的 64位数,导致舍入问题
    assert(!E(dx, (double) (int) 0));    // 除数为零
    return 0;
}

2.90

#include <stdio.h>
#include <assert.h>
#include <math.h>

float u2f(unsigned x) {
  return *(float*) &x;
}

/* 2^x */
float fpwr2(int x) {
  /* Result exponent and fraction */
  unsigned exp, frac;
  unsigned u;

  if (x < 2-pow(2,7)-23) {
    /* too small. return 0.0 */
    exp = 0;
    frac = 0;
  } else if (x < 2-pow(2,7)) {
    /* Denormalized result */
    exp = 0;
    frac = 1 << (unsigned)(x - (2-pow(2,7)-23));
  } else if (x < pow(2,7)-1+1) {
    /* Normalized result */
    exp = pow(2,7)-1+x;
    frac = 0;
  } else {
    /* Too big, return +oo */
    exp = 0xFF;
    frac = 0;
  }

  /* pack exp and frac into 32 bits */
  u = exp << 23 | frac;
  /* Result as float */
  return u2f(u);
}

int main(int argc, char* argv[]) {
  assert(fpwr2(0) == powf(2,0));
  assert(fpwr2(100) == powf(2,100));
  assert(fpwr2(-100) == powf(2,-100));
  assert(fpwr2(10000) == powf(2,10000));
  assert(fpwr2(-10000) == powf(2,-10000));
  return 0;
}

2.91

A.
0b11.0010010000111111011011

B.
0b11.001001(001)...

C.
第九个

2.92

float_bits float_negate(float_bits f) {
    unsigned sign = f >> 31;
    unsigned exp = f >> 23 & 0xff;
    unsigned frac = f & 0x7fffff;
    if (exp == 0xff && frac) {
        return f;
    }
    return (~sign << 31) | (exp << 23) | frac;
}

2.93

float_bits float_absval(float_bits f) {
    unsigned sig = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;

    int is_NAN = (exp == 0xFF) && (frac != 0);
    if (is_NAN) {
        return f;
    }

    return 0 << 31 | exp << 23 | frac;
}

2.94

float_bits float_twice(float_bits f) {
    unsigned sig = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;

    int is_NAN_or_oo = (exp == 0xFF);
    if (is_NAN_or_oo) {
        return f;
    }

    if (exp == 0) {
        /* Denormalized */
        frac <<= 1;
    } else if (exp == 0xFF - 1) {
        /* twice to oo */
        exp = 0xFF;
        frac = 0;
    } else {
        /* Normalized */
        exp += 1;
    }

    return sig << 31 | exp << 23 | frac;
}

2.95

float_bits float_half(float_bits f) {
    unsigned sig = f >> 31;
    unsigned rest = f & 0x7FFFFFFF;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;

    int is_NAN_or_oo = (exp == 0xFF);
    if (is_NAN_or_oo) {
        return f;
    }

    /*
     * round to even, we care about last 2 bits of frac
     *
     * 00 => 0 just >>1
     * 01 => 0 (round to even) just >>1
     * 10 => 1 just >>1
     * 11 => 1 + 1 (round to even) just >>1 and plus 1
     */
    int addition = (frac & 0x3) == 0x3;

    if (exp == 0) {
        /* Denormalized */
        frac >>= 1;
        frac += addition;
    } else if (exp == 1) {
        /* Normalized to denormalized */
        rest >>= 1;
        rest += addition;
        exp = rest >> 23 & 0xFF;
        frac = rest & 0x7FFFFF;
    } else {
        /* Normalized */
        exp -= 1;
    }

    return sig << 31 | exp << 23 | frac;
}

2.96

int float_f2i(float_bits f) {
    unsigned sig = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;
    unsigned bias = 0x7F;

    int num;
    unsigned E;
    unsigned M;

    /*
     * consider positive numbers
     *
     * 0 00000000 00000000000000000000000
     *   ===>
     * 0 01111111 00000000000000000000000
     *   0 <= f < 1
     * get integer 0
     *
     * 0 01111111 00000000000000000000000
     *   ===>
     * 0 (01111111+31) 00000000000000000000000
     *   1 <= f < 2^31
     * integer round to 0
     *
     * 0 (01111111+31) 00000000000000000000000
     *   ===>
     * greater
     *   2^31 <= f < oo
     * return 0x80000000
     */
    if (exp >= 0 && exp < 0 + bias) {
        /* number less than 1 */
        num = 0;
    } else if (exp >= 31 + bias) {
        /* number overflow */
        /* or f < 0 and (int)f == INT_MIN */
        num = 0x80000000;
    } else {
        E = exp - bias;
        M = frac | 0x800000;
        if (E > 23) {
            num = M << (E - 23);
        } else {
            /* whether sig is 1 or 0, round to zero */
            num = M >> (23 - E);
        }
    }

    return sig ? -num : num;
}

2.97

#include <stdio.h>
#include <assert.h>
#include <limits.h>

typedef unsigned float_bits;

float_bits float_i2f(int i) {
    unsigned sign = i & 0x80000000;
    if (i == 0) {
        return sign;
    }
    if (i == 0x80000000) {
        return 0xcf000000;
    }

    unsigned transI = i;
    if (sign) {
        transI = ~i + 1;
    }
    int noSignI = transI & 0x7fffffff;

    int isOne = noSignI & 0x80000000;
    int count = 1;

    while (!isOne) {
        noSignI <<= 1;
        isOne = noSignI & 0x80000000;
        count++;
    }

    int exp = 127 + (32 - count);
    int frac = (transI << count >> 1 + 8) & 0x7fffff;

    if (32 - count > 23) {
        int addition = 0;
        int mid = (transI << count >> 1 + 8 << 1 + 8) + 0b100000000;
        if (transI << count > mid) {
            addition++;
        } else {
            if (transI << count == mid && frac & 0x1) {
                addition++;
            }
        }
        frac += addition;
        if (addition && frac == 0x800000) {
            frac = 0;
            exp += 1;
        }
    }
    return sign | exp << 23 | frac;
}

int main() {
    unsigned a;
    int b;
    int arr[] = {1, 2, 4, INT_MAX, INT_MIN, 0, -1, -2, 123456789, 2147483582, 2147483584, 2147483585};
    int count = sizeof(arr) / sizeof(int);
    for (int i = 0; i < count; i++) {
        b = arr[i];
        a = float_i2f(b);
        printf("\n------  %d ==\t", b);
        printf("------  %f ==\t", (float) b);
        printf(" %f  ???-------\n", *(float *) (&a));
        assert((float) b == *(float *) (&a));
    }
    return 0;
}
show-bytes.c代码解释 代码功能 展示了数据在内存中的形式及其所在地址,可以看出大小端模式,强制类型转换发生的溢出。 代码分析 typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for (i = 0; i < len; i++) printf("%p\t... 阅读详情

相关推荐

is-little-endian:检查您的系统是否为小端

is-little-endian 检查您的系统是否为小端。 基本上是一个捷径: ( ( new Uint32Array ( ( new Uint8Array ( [ 1 , 2 , 3 , 4 ] ) ) . buffer ) ) [ 0 ] === 0x04030201 ) 用法 使用 npm 安装: npm install is-little-endian 然后像这样使用它: if ( require ( "is-little-endian" ) ) { // Use little endian buffer } else { // Use big endian buffer } 学分 (c) 2013 米科拉·李森科。 BSD 许可证

深入理解计算机系统 csapp 家庭作业(第二章完整版)

csapp第二章家庭作业答案 完整版

m0_64764193的博客 1万+

《深入理解计算机系统》家庭作业的答案

经典名著 深入理解计算机系统, 在你完成阅读的时候,如何检测学习的程度,这里给你提供了课后题的答案,让你对每一个问题茅塞顿开。

C语言:输出每个对象的字节表示

C语言:输出每个对象的字节表示 #include <stdio.h> typedef unsigned char *byte_pointer; //定义了一个指向unsigned char的数据类型byte_pointer,一个字节指针引用一个字节序列,每个字节都被认为是一个非负整数 //输出每个对象的十六进制字节表示 void show_bytes(byte_pointer start, size_t length) //size_t表示数据结构大小的首选数据类型 { size_t

weixin_43456810的博客 735

深入理解计算机系统第二章作业

深入理解计算机系统第二章课后部分练习题作业答案,有两处错误哦~

AHB不对称半桥反激电路设计(一)变换器拓扑工作原理详解

本文详细分析了AHB(不对称半桥)反激变换器拓扑的工作原理及关键优势。该拓扑通过谐振腔结构实现原边功率管的零电压开通(ZVS)和副边整流管的零电流关断(ZCS),显著提升效率至95%以上。文章阐述了6个工作阶段的时序特征,包括谐振电感电流和电容电压的数学模型推导。AHB拓扑具有漏感能量回收、宽电压输出(适配PD快充等场景)和协同储能等优势,相比传统方案可缩小变压器体积30%,成为100-300W隔离电源的理想选择。

【Simon】的博客 7160

深入理解计算机系统第二章家庭作业

D:不总是返回1.例如dx与dy互为倒数且dy*dz=+infinite。C: 0x4049039b 0x40492492 从高位向低位第19个。E:不总是返回1.例如dx=1.0, dz=0.0。B: y=1, k=3, 即 0b11.(001)*B:不总是返回1.如x=INT_MIN,Y=1。A:当x是最小值时,其负数还是最小值。- x 即 x = Y/(2。

weixin_44918105的博客 1088

告别调参玄学:用 DINOv2 (ViT-S/ViT-G) 和 PCA 可视化,直观理解自监督特征

本文深入解析了DINOv2(ViT-S/ViT-G)模型在自监督学习中的特征提取机制,通过PCA降维技术实现特征空间的可视化。文章对比了不同规模模型的特征表达差异,并提供了PCA阈值调优和深度分析的实用技巧,帮助读者直观理解自监督学习的视觉密码。

weixin_42565865的博客 410

《深入理解计算机系统》(CSAPP)读书笔记 —— 第二章 信息的表示和处理

本章主要研究了计算机中无符号数,补码,浮点数的编码方式,通过研究数字的实际编码方式,我们能够了解计算机中不同类型的数据可表示的值的范围,不同算术运算的属性,可以知道计算机是如何处理数据溢出的。了解计算机的编码方式,对于我们写出可以跨越不同机器,不同操作系统和编译器组合的代码具有重要的帮助。 文章目录信息存储为什么会有二进制?二进制有什么含义和优势?计算机的三种编码方式整数&浮点数虚拟内存&虚拟地址空间二进制&十进制&十六进制二进制转十六进制(分组转换)十进制转十六进制虚拟.

嵌入式与Linux那些事的博客 9331

信创服务器(麒麟 V10 SP3)安装 NVIDIA GeForce RTX 5070 驱动

本文介绍了在麒麟V10 SP3系统上安装NVIDIA RTX 5070显卡驱动的详细步骤。首先需要关闭nouveau驱动,安装必要的编译环境和工具,确保内核版本与kernel-devel完全一致。最后运行NVIDIA驱动安装程序,关键选择包括启用DKMS支持、编译模块、禁用32位兼容和nouveau驱动。整个流程适用于海光CPU和Blackwell架构GPU的国产操作系统环境。

猿小白的博客 679

AUTOSAR CP R18-10 架构总览与导航

AUTOSAR CP R18-10 架构总览 本文档系统整理了AUTOSAR CP R18-10版本的199篇技术规范,涵盖7大架构层级: 应用层(15篇):包含车身舒适、底盘控制、HMI、安全系统、动力系统等AI应用 RTE(1篇):虚拟功能总线规范 服务层(159篇):细分为系统服务(OS/ECU管理/加密)、存储服务、通信服务(CAN/LIN/Ethernet) ECU抽象层(20篇):I/O与通信硬件抽象 MCAL(41篇):微控制器驱动层 复杂驱动(14篇):CDD设计与SPAL支撑 规范模板(2

一名留德华的,康德的信徒的,专注于汽车电子领域的博客 722

数据对象的十六进制字节表示

这段代码主要是学习强制转换,同时把一些数据类型也搞得更清楚一些,还有转化为字节表示的方法。 typedef unsigned char *byte_pointer; 这条语句看到一个更加通顺的解释 将byte_pointer 指向 类型为unsigned char对象 的 指针。(明确重命名之后他是一个指针,指向的数据类型) show_byte 输入字节序列的地址,取字节数,打印出每个以十六进制...

alike_meng的博客 1880

2026.2.23:AgentScope框架实战<一>:安装并使用agentscope

本文介绍了AgentScope框架的安装与使用实践。通过PyPI安装agentscope[full]后,演示了如何创建ReActAgent代理:1)配置DashScope聊天模型;2)注册自定义工具函数(查询位置和天气);3)初始化代理并处理用户请求。示例展示了代理如何响应复合查询(如同时获取北京位置和天气信息),输出结果显示代理成功执行了工具调用并返回结构化响应。该框架支持Python 3.13环境,提供内存管理、工具集成等功能,适用于构建智能代理系统。

拥抱具身智能,昇腾Ascend C 509

计算机课外作业,深入理解计算机系统 (第二章课外作业)

当前位置:我的异常网» 操作系统»深入理解计算机系统 (第二章课外作业)深入理解计算机系统 (第二章课外作业)www.myexceptions.net网友分享于:2013-12-24浏览:7次深入理解计算机系统 (第二章家庭作业)如题,家庭作业。记录个人的部分答案,由于时间关系,不会每题都做。2.38:show_bytes()直接参照书本里面的程序:#include #include ...

weixin_36172296的博客 181

【AUTOSAR实战】:CAN发送邮箱忙导致报文发送丢帧的问题调试

本文档主要讨论了CAN总线通信中可能出现的TC377传输错误的分析和解决方案。文章提供了如何通过检查CAN传输和接收过程、识别传输缓冲区的类型和状态以及选择适当的内存保护功能来检测和解决此类错误的见解。经过多次尝试和分析,得出的结论是,修改CANIF缓冲的尺寸并重新分配报文给各个buffer并不能解决问题。此外,发送中断被抢占可能导致报文无法发送,最终也将此因素排除。本文档还提到了一些可能导致发送流程调度出现问题的因素,例如CANIF中报文引用Buffer不合理。

weixin_46481662的博客 3140

构建自己的 Qt 插件系统

Qt 本身提供了插件相关的技术,但并没有提供一个通用的插件框架!倘若要开发一个较大的 GUI 应用程序,并希望使其可扩展,那么拥有这样一个插件框架无疑会带来很大的好处。

青春不老,奋斗不止! 2万+

20135317的博客目录

【大三下学期】Linux及安全课程博客 (1)Linux内核分析——网易云课堂 LINUX内核分析第一周学习总结:计算机是如何工作的? LINUX内核分析第二周学习总结:操作系统是如何工作的? LINUX内核分析第三周学习总结:构造一个简单的LINUX系统MENUOS LINUX内核分析第四周学习总结:扒开系统调用的三层皮(上) LINUX内核分析第五周学习总结:扒开系统调用的三层皮(下) LI...

weixin_30467087的博客 109

一文学会python基础知识

1. python 运行环境 1.1 脚本式环境 1.2 交互式环境 2. python 注释 3. 变量及变量命名 4. 关键词 BIFS 5. 标准操作符 6. 条件判断 7. 循环 8. python 数据类型 9. python 序列 9.1 序列-字符串(str) 9.2 序列-列表 9.3 序列-元组 10. 字典 11. 集合 12. python内存管理及可变、不可变对象 13. 函数 13.1 函数参数 13.2 return and yiled(生成器) 13.3 参数传递处理 ...

weixin_43178406的博客 26万+

20135337——信息安全设计基础第十四周学习笔记

每周读书笔记链接汇总 第一周读书笔记 实验楼-Linux基础 第二周读书笔记 第一章 计算机系统漫游;VIM基础 第三周读书笔记 第二章 信息的表示和处理 第四周读书笔记 第三章 程序的机器级表示 第五周读书笔记 第四章 处理器体系结构 第六周读书笔记 第六章 存储器层次结构 第七周读书笔记 中期小结 第八周读书笔记 第十章 系统级I/O 第九周读书笔记 ls、who、echostate等命令的具...

weixin_34085658的博客 226

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

d

#include<stdio.h> typedef unsigned char* byte_pointer; /* size_t 与int的区别 在32位架构中被普遍定义为: typedef unsigned int size_t; 而在64位架构中被定义为: typedef unsigned long size_t; size_t取值用来表示最大可能的数组尺寸 */ void ...

weixin_45373958的博客 135

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

查看电脑大小端法以及使用unsigned char *byte的原因

(下面是cmu的代码) /* show-bytes - prints byte representation of data */ /* $begin show-bytes */ #include <stdio.h> /* $end show-bytes */ #include <stdlib.h> #include <string.h> /* $be...

qq_45109990的博客 1039

2.57-编写程序show_short, show_long和show_double,它们分别打印类型为short, long和double的C语言对象的字节表示。请试着在几种机器上运行。

#include <stdio.h> //A byte pointer refers to a sequence of bytes typedef unsigned char * byte_pointer; //The input is a byte pointer and a byte number void show_bytes(byte_pointer start, size_t len) { size_t i; for (i = 0; i < len; i++) { /

weixin_45861496的博客 1175

《深入理解计算机系统》学习心得二:关于show-bytes的 学习

此段代码,使用强制类型转换来访问和打印不同程序对象的字节表示。show-bytes打印出每个以十六进制表示的字节。 /* show-bytes - prints byte representation of data */ /* $begin show-bytes */ #include <stdio.h> /* $end show-bytes */ #includ...

欢迎来到我的博客 1476

深入理解计算机系统第三版家庭作业答案-第二章

2.55-2.57答案:show_bytes 源代码:#include&lt;stdio.h&gt; typedef unsigned char* byte_pointer; void show_bytes(byte_pointer ch, int len){ printf("show bytes:"); for (int i = 0; i &lt; len; i++) ...

baidu_41108490的博客 2万+

计算机中的字节序问题

程序设计中的数据类型有很多事跨多个字节的,比如char是用一个字节表示,而诸如int,float类型则用4个字节表示double则用8个字节表示,我们知道,数据对象实例是存储在一定地址单元中的,我们也知道,存储器中的每个字节都由一个唯一的地址标志或者是存储。那么当数据对象跨多个字节时,各字节时如何安排存储的呢?这就是字节序的问题。

《致青春》——云梦泽 1286
上一篇: 动态改变 rem 大小
下一篇: redis 配置
OneGoal
博客等级 码龄10年 28粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值