注意点
- 计算机一般使用8位的块或者字节作为最小的可寻址的单位。而不是直接对位进行编码。
- 虚拟存储器 :一个字节数组
- 虚拟地址空间:所有可能的地址
- 一个指针的值都是 存储块的第一个字节的虚拟地址。指针的类型是由编译器来维护的,具体的机器代码却没有关于数据类型的信息。
- C语言里面 0x|0X aA
- 字长,虚拟空间是以一个字来编码的,所以字的大小决定了虚拟空间的大小。
- 多字节对象存储为连续的,地址为字节中最小的地址。
- 小端就是 最低位先放,大端就是 最高位先放
- 十进制数x的ASCII码就是0x3x
- ASCII具有更加好的平台独立性,字节顺序无关大小端。
- 无符号数字截断到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=2k∗4+b=2b000(k个0)
220=1024∗1024=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
- 0x00 35 91 41 = 0000 0000 0011 0101 1001 0001 0100 0001
- 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
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
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)
总结
- 对B,C,D,E的二进制不熟悉 就记住AC吧 1010 1100
- 4*k + b里面如果b=0 则为1 反之也如此
- xor: LEARNED: bis(bic(x,y),bic(y,x))
- !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);
}