信息的表示

注意点

  1. 计算机一般使用8位的块或者字节作为最小的可寻址的单位。而不是直接对位进行编码。
  2. 虚拟存储器 :一个字节数组
  3. 虚拟地址空间:所有可能的地址
  4. 一个指针的值都是 存储块的第一个字节的虚拟地址。指针的类型是由编译器来维护的,具体的机器代码却没有关于数据类型的信息。
  5. C语言里面 0x|0X aA
  6. 字长,虚拟空间是以一个字来编码的,所以字的大小决定了虚拟空间的大小。
  7. 多字节对象存储为连续的,地址为字节中最小的地址。
  8. 小端就是 最低位先放,大端就是 最高位先放
  9. 十进制数x的ASCII码就是0x3x
  10. ASCII具有更加好的平台独立性,字节顺序无关大小端。
  11. 无符号数字截断到k位就是等价于x mod 2^k,补码的话还要加上2^n.

练习题

2.1

A. 0x39A7F8 = 0011 1001 1010 0111 1111 1000
B. 1100 1001 0111 1011 = 0xC98B ->0xC97B

C. 0xD5E4C = 1100 0101 1110 0100 1010 -> 1101 0101 1110 0100 1100
D. 10 0110 1110 0111 1011 0101 = 0x26E7C5 -> 0x26E7B5

2.2

210=1024 , 2n=2k4+b=2b000(k0)
220=10241024=1000000+48000+576=1048576

n 2n 10进制 2n 16进制
9 512 0x200
19 524288 0x80000
14 16384 0x4000
16 65535 0x10000|
17 131072 0x10000->0x20000
5 32 0x10->0x20
7 128 0x80

2.3

167 = 16 * 10 + 7

十进制 二进制 十六进制
0 0000 0000 0x00
167 1010 0111 0xA7
62 0011 1100-> 0011 1110 0x3D->0x3E
188 1011 1100 0xCD->0xBC
55 0011 0111 0x37
136 1000 1000 0x88
243 1111 0011 0xF3
82 0101 0010 0x52
172 1010 1100 0xAC
231 1110 0111 0xE7

2.4

A. 0x503c + 0x8 = 0x5044
B. 0x503c - 0x40 = 0x4ffc
C. 0x503c + 64 = 0x503c +0x40 = 0x507c
D. 0x50ea-0x503c = 0xad->0xae

2.5

* 小端 大端
A 21 87
B 21 43 87 65
C 21 43 65 87 65 43

2.6

  1. 0x00 35 91 41 = 0000 0000 0011 0101 1001 0001 0100 0001
  2. 0x4A 56 45 04 = 0100 1010 0101 0110 0100 0101 0000 0100

2.7

#include <stdio.h>
#include <cstring>
typedef unsigned char* byte_pointer;
void show_bytes(byte_pointer start,int len) {
    for (int i = 0;i < len;i ++) {
        printf(" %.2x",start[i]);
    }
    puts("");
}
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) {
    show_bytes((byte_pointer)&x,sizeof(void *));
}
int main() {
    const char *s = "abcdef";
    show_bytes((byte_pointer)s,strlen(s)); 
}

2.8

运算 结果
a [0110 1001]
b [0101 0101]
~a [1001 0110]
~b [1010 1010]
a & b [0100 0001]
a [0111 1101]
a ^ b [0011 1100]

2.9

A.

- -
111 011
110 010
101 001
100 000

B.
1. 001 | 010 = 011 蓝绿色
2. 110 & 011 = 010 绿色
3. 100 ^ 101 = 001 蓝色

2.10

#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
void inplace_swap(int *x,int *y) {
    *y = *x ^ *y;
    *x = *y ^ *x;
    *y = *y ^ *x;
}
int main() {
    int a = 1;
    int b = 2;
    inplace_swap(&a,&b);
    cout <<a << " " << b << endl; 
}

2.11

#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
void inplace_swap(int *x,int *y) {
    *y = *x ^ *y;
    *x = *y ^ *x;
    *y = *y ^ *x;
}

void reverse_array(int a[],int cnt) {
    int first, last;
    for (first = 0,last = cnt-1;first **<=** last;first ++,last --) {
        inplace_swap(&a[first],&a[last]);
    }
    for (int i = 0;i < cnt;i ++) {
        cout << a[i] << " " ;
    }
    cout << endl;
}


int main() {
    int a[5] = {1,2,3,4,5};
    reverse_array(a,5);
}

2.12

A. x & 0xff
B. x ^ (~0xff)
C. x | 0xff

2.13

or: bis(x,y)
xor: LEARNED: bis(bic(x,y),bic(y,x))
因为bic(x,m) = x & ~m
x^y = (x & ~y) | (y & ~x)

2.14

x = 0x66,y = 0x39
x = 0110 0110
y = 0011 1001

表达式
x & y 0010 0000
x | y 0111 1111
~x | ~y 1101 1111
x & !y 0100 0110 -> 0000 0000
x && y 0x1
x || y 0x1
!x || !y 0x0
x && ~y 0x0

2.15

x & ~y == 0 -> !(x ^ y)

2.16

十六进制 二进制 二进制 x<<3 十六进制x<<3 二进制x>>2 十六进制x>>2 二进制x>>2 十六进制x>>2
0xC3 1100 0011 0001 1000 0x18 0011 0000 0x30 1111 0000 0xf0
0x75 0111 0101 1010 1000 0xA8 0001 1101 0x1D 0001 1101 0x1D
0x87 1000 0111 0011 1000 0x38 0010 0001 0x21 1110 0001 0xE1
0x66 0110 0110 0011 0000 0x30 0001 1001 0x19 0001 1001 0x19

2.17

十六进制 二进制 无符号数 补码
0xE 1110 14 -2
0x0 0000 0 0
0x5 0101 5 5
0x8 1000 8 -8
0xD 1101 13 -3
0xF 1111 15 -1

2.18

十六进制 二进制
0x1b8 440
0x14 20
0xffff fe58 0x258 = -424
0xffff fe74 0x1e74 = 0x274 = 4 + 16*7-2*256 = 116-512 = -396
0x44 68
0xffff fec8 0x2c8 = 8 + 12*16 - 2 * 256=200 - 512 = -312
0x10 16
0xc 12
0xffff feec 0x2ec = 12 + 16*14 - 2 * 256 = -500 + 224 = -276
0x20 32

2.19

x T2U4(x)
-8 8
-3 13
-2 14
-1 15
0 0
5 5

2.20

2.21

表达式 类型 求值
-2147483647-1==2147483648U 无符号 1
-2147483647-1 < 2147483647 有符号 1
-2147483647-1U <2147483647 无符号 0
-2147483647-1<-2147483647 有符号 1
-2147483647-1U <-2147483647 无符号 1

2.22

2.23

w fun1(w) fun2(w)
0x00000076 0x00000076 0x00000076
0x87654321 0x00000021 0x00000021
0x000000C9 0x000000C9 0xFFFFFFC9
0xEDCBA987 0x00000087 0xFFFFFF87

2.24

从N位变成M位,如果是无符号数直接x mod 2^M
如果是有符号数先把他看成无符号数然后再变回有符号数
那就是(x + 2^N) % (2 ^ M) = x % 2 ^M.
所以无论是有符号数还是无符号数都先mod 2 ^M然后如果是有符号数再进行处理下

原始值 无符号 补码
0 0 0
2 2 2
9 1 1
11 3 3
15 7 -1
原始值 无符号 补码
0 0 0
2 2 2
-7 9 1
-5 11 3
-1 15 -1

2.25

错误原因: unsigned int - 1其实等于最大值了,然后i <= 最大值恒为真

float sum_elements(float a[],unsigned length) {
    int i;
    float result = 0;
    for (i = 0,`i <= length-1`;i ++) {
        result += a[i];
    }
    return result;
}

改成i < length
或者是int length

2.26

size_t strlen(const char* s);
int strlonger(char* s,char *t) {
    reutnr strlen(s) - strlen(t)  > 0;
}

改成strlen(s) > strlen(t)

总结

  1. 对B,C,D,E的二进制不熟悉 就记住AC吧 1010 1100
  2. 4*k + b里面如果b=0 则为1 反之也如此
  3. xor: LEARNED: bis(bic(x,y),bic(y,x))
  4. !x的结果要不是0要不是1。

代码

#include <stdio.h>
typedef unsigned char* byte_pointer;

void show_bytes(byte_pointer start,int len) {
    for (int i = 0;i < len;i ++) {
        printf(" %.2x",start[i]);
    }
    puts("");
}
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) {
    show_bytes((byte_pointer)&x,sizeof(void *));
}
int main() {
    show_int(16);
}

你可能感兴趣的:(计算机系统)