信息的表示

注意点

  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进制
95120x200
195242880x80000
14163840x4000
16655350x10000|
171310720x10000->0x20000
5320x10->0x20
71280x80
2.3

167 = 16 * 10 + 7

十进制二进制十六进制
00000 00000x00
1671010 01110xA7
620011 1100-> 0011 11100x3D->0x3E
1881011 11000xCD->0xBC
550011 01110x37
1361000 10000x88
2431111 00110xF3
820101 00100x52
1721010 11000xAC
2311110 01110xE7
2.4

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

2.5
*小端大端
A2187
B21 4387 65
C21 43 6587 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.

--
111011
110010
101001
100000

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 & y0010 0000
x | y0111 1111
~x | ~y1101 1111
x & !y0100 0110 -> 0000 0000
x && y0x1
x || y0x1
!x || !y0x0
x && ~y0x0
2.15
x & ~y == 0 -> !(x ^ y)

2.16

十六进制二进制二进制 x<<3十六进制x<<3二进制x>>2十六进制x>>2二进制x>>2十六进制x>>2
0xC31100 00110001 10000x180011 00000x301111 00000xf0
0x750111 01011010 10000xA80001 11010x1D0001 11010x1D
0x871000 01110011 10000x380010 00010x211110 00010xE1
0x660110 01100011 00000x300001 10010x190001 10010x19
2.17
十六进制二进制无符号数补码
0xE111014-2
0x0000000
0x5010155
0x810008-8
0xD110113-3
0xF111115-1
2.18
十六进制二进制
0x1b8440
0x1420
0xffff fe580x258 = -424
0xffff fe740x1e74 = 0x274 = 4 + 16*7-2*256 = 116-512 = -396
0x4468
0xffff fec80x2c8 = 8 + 12*16 - 2 * 256=200 - 512 = -312
0x1016
0xc12
0xffff feec0x2ec = 12 + 16*14 - 2 * 256 = -500 + 224 = -276
0x2032
2.19
x T2U4(x)
-88
-313
-214
-115
00
55
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
wfun1(w)fun2(w)
0x000000760x000000760x00000076
0x876543210x000000210x00000021
0x000000C90x000000C90xFFFFFFC9
0xEDCBA9870x000000870xFFFFFF87
2.24

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

原始值无符号补码
000
222
911
1133
157-1
原始值无符号补码
000
222
-791
-5113
-115-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
十六进制十进制十进制十六进制
0015F
5510A
8877
D1322
F1500
2.29
x y x+y x+5y 情况
10100 -1210001 -15100101 -2700101 53
11000 -811000 -8110000 -1610000 -162
10111 -901000 811111 -11111 -12
00010 200101 500111 70111 72
01100 1200100 4010000 1610000 -161
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
十六进制十进制十进制十六进制
0000
5511B
8888
D1333
F1511
2.34
模式xyx*y截断的x*y
无符号1001014*5=20 0001 10004 100
有符号100101-4*-3=12 0000 1100-4 100
无符号0101112*7=14 0000 11106 110
有符号0101112*-1=-2 110-2 110
无符号1101106*6=36 0010 01004 100
有符号110110-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移位加减法表达式
621(x<<2)|(x<<1)
311132-1 (x<<5)-x
-621-4-2 -(x<<2)-(x<<1)
552264-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) < 0INT_MIN
(x & 7) != 7 || (x << 29 < 0)TRUE
(x * x) >= 0(1<<15 | 1<<14)
x < 0 || -x <= 0TRUE
x > 0 || -x >= 0INT_MIN
x + y == ux + uyTRUE
x * ~y +uy*ux == -xTRUE

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

2.45
小数值二进制表示十进制表示
18 0.0010.125
34 0.110.75
2516 1.10011.5625
4316 10.10112.6875
98 1.0011.125
478 101.1115.875
5116 11.00111.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
eE 2E fM 2EM V十进制
0 00 0000100000
0 00 01001 14 14 14 18 0.125
0 00 10001 24 24 24 24 0.25
0 00 11001 34 34 34 34 0.75
0 01 0010101111
0 01 01101 14 114 1 14 114 1.25
0 01 10101 24 1 24 1 24 124 1.5
0 01 11101 34 1 34 1 34 1 34 1.75
0 10 00212 04 1222
0 10 01212 14 1 14 104 52 2.5
0 10 10212 24 1 24 124 33
0 10 11212 34 1 34 144 72 3.5
0 11 00inf
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 000010011 0001
101 11107.75101 1117.75
010 10010.78125010 1000.75
110 111115.5111 00016
000 00011/4000?
2.53
表达式
x == (int)(double)xTrue
x==(int)(float)xINT_MAX
d==(double)(float)dINT_MAX
f==(float)(double)fTrue
f==-(-f)True
1.0/2==1/2.0True
d*d >= 0.0True
(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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值