信息的表示

注意点

  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.
  12. 负数计算,如果是无符号数的话: x + y := 0 mod 2^m也就是-0 = 0,x = 2^m - x。如果是补码的话,-INT_MIN=INT_MIN,其他一样。1
  13. 浮点数从 0 000 0000 不断递增, 直到0 111 0000停止都是比较正常的数字后面都是NaN. 对于 0 000 * 系列数字 阶码等于下一组数的阶码也就是1(2k11)=22k1 数的值就是数的值。 从下一组开始就是阶码不为0开始,阶码等于x-bias=x-(2^{k-1}-1),数的值等于1+数的值。
  14. 向偶数舍入,如果是0.5那么就是向偶数前进,其他就取最近的了。

练习题

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)

2.27

2.28

十六进制 十进制 十进制 十六进制
0 0 15 F
5 5 10 A
8 8 7 7
D 13 2 2
F 15 0 0

2.29

x y x+y x+5y 情况
10100 -12 10001 -15 100101 -27 00101 5 3
11000 -8 11000 -8 110000 -16 10000 -16 2
10111 -9 01000 8 11111 -1 1111 -1 2
00010 2 00101 5 00111 7 0111 7 2
01100 12 00100 4 010000 16 10000 -16 1

2.30

int tadd_ok(int x,int y) {
    bool ok = true;
    if(x > 0 && y > 0 && x + y `< -> <=` 0) ok = false;
    if(x < 0 && y < 0 && x + y `> -> >=` 0) ok = false;
    if(ok) return 1;
}

2.31

如果是正溢出,那么x+y = x +y -2^m
然后sum - x = x + y - 2^m -x = y - 2^m < 2^m-1
所以y-2^m = y-2^m+2^m=y
其他同理

2.32

当y时负数的时候,输入x-y x<0认为呢不会溢出,但是当y=INT_MIN的时候,-y=INT_MIN,所以返回溢出了。

int tadd_ok(int x,int y) {
    bool ok = true;
    if(x > 0 && y > 0 && x + y <= 0) ok = false;
    if(x < 0 && y < 0 && x + y >= 0) ok = false;
    if(ok) return 1;
    return 0;
}
int main() {
    int x = -2147483647 - 1;
    cout << tadd_ok(-100,x) << endl;
}

2.33

十六进制 十进制 十进制 十六进制
0 0 0 0
5 5 11 B
8 8 8 8
D 13 3 3
F 15 1 1

2.34

模式 x y x*y 截断的x*y
无符号 100 101 4*5=20 0001 1000 4 100
有符号 100 101 -4*-3=12 0000 1100 -4 100
无符号 010 111 2*7=14 0000 1110 6 110
有符号 010 111 2*-1=-2 110 -2 110
无符号 110 110 6*6=36 0010 0100 4 100
有符号 110 110 -2*-2=4 -4 100

2.35 待完成

2.36

int tmult_ok(int x,int y) {
    long long pll = (long long)x * y;
    return pll == (int) pll;
}

2.37

malloc的传参数的时候会进行类型转换。

if(x != (unsigned)x)

2.38

2^k或者2^k+1

2.39

-(1<<m)

2.40

K 移位 加减法 表达式
6 2 1 (x<<2)|(x<<1)
31 1 1 32-1 (x<<5)-x
-6 2 1 -4-2 -(x<<2)-(x<<1)
55 2 2 64-8-1 (x<<6)-(x<<3)-x

2.41

第一个有n-m+1个
第二个有2个
所以如果n-m+1 < 2用第一个
如果n-m+1=2随便
其他用第二个

2.42

int div16(int x) {
    int flag = `(x >> 31)` & 0xF; //这里产生一个字
    return (x + flag) >> 4;
}

2.43

M=31,N=8

2.44

表达式 特例
(x > 0) || (x - 1) < 0 INT_MIN
(x & 7) != 7 || (x << 29 < 0) TRUE
(x * x) >= 0 (1<<15 | 1<<14)
x < 0 || -x <= 0 TRUE
x > 0 || -x >= 0 INT_MIN
x + y == ux + uy TRUE
x * ~y +uy*ux == -x TRUE

x(y1)+uyux=xyx+uyux=x

2.45

小数值 二进制表示 十进制表示
18 0.001 0.125
34 0.11 0.75
2516 1.1001 1.5625
4316 10.1011 2.6875
98 1.001 1.125
478 101.111 5.875
5116 11.0011 1.1875

2.46

0.2 = 1/5 = 3/16 + 3/16^2+… =(3/16-0)/(1-1/16) = 1/5
A. 0…..1100 1100
B. 2^-20 * 1/10 = 9.54*10-8
C. 9.54*10-8*100*60*60*10 = 0.343
D. 0.343*2000 = 687

2.47

e E 2E f M 2EM V 十进制
0 00 00 0 0 1 0 0 0 0 0
0 00 01 0 0 1 14 14 14 18 0.125
0 00 10 0 0 1 24 24 24 24 0.25
0 00 11 0 0 1 34 34 34 34 0.75
0 01 00 1 0 1 0 1 1 1 1
0 01 01 1 0 1 14 114 114 114 1.25
0 01 10 1 0 1 24 124 124 124 1.5
0 01 11 1 0 1 34 134 134 134 1.75
0 10 00 2 1 2 04 1 2 2 2
0 10 01 2 1 2 14 114 104 52 2.5
0 10 10 2 1 2 24 124 124 3 3
0 10 11 2 1 2 34 134 144 72 3.5
0 11 00 inf
0 11 01 不合法
0 11 10 不合法
0 11 11 不合法

2.48

3510493 = 11 0101 1001 0001 0100 0001 = 1.1 0101 1001 0001 0100 0001 * 2^21
21+127 = 128 + 20 = 1001 0100
0 1001 0100 1 0101 1001 0001 0100 0001 00
0100 1010 0101 0110 0100 0101 0000 0100
4A564504

2.49待完成

2.50

A. 10.010 10.0
B. 10.011 10.1
C. 10.110 11.0
D. 11.001 11.0

2.51

0.0 0011 0011 0011 0011 0011 01

#### 2.52
bias = 2^2-1=3
3-3=0
4*(1+1-1/16)=8 - 1/4
1/2*(1+1/2+1/16) = 1/2 * 25/16
1/2*(1+1/2) = 3/4
8*(2-1/16) = 16-1/2=15.5
1.1111 = 10.000
1/4*1
0001 0010

011 0000 1 0011 000 1
101 1110 7.75 101 111 7.75
010 1001 0.78125 010 100 0.75
110 1111 15.5 111 000 16
000 0001 1/4 000?

2.53

表达式
x == (int)(double)x True
x==(int)(float)x INT_MAX
d==(double)(float)d INT_MAX
f==(float)(double)f True
f==-(-f) True
1.0/2==1/2.0 True
d*d >= 0.0 True
(f+d)-f==d 溢出

总结

  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。
  5. -(1<<m)
    6.有限范围内的数的运算是模的运算,无符号数和补码在位级运算是一样的。 unsigned很容易出bug。

代码

#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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章