一. 再探位运算
1.1 左移 «
左移运算符将运算对象向左移动指定的位数,移出左末端位的值丢失,用 0 填充空出的空位
(111001)« 2
(100100)
1.2 右移 »
右移运算符将运算对象向右移动指定的位数,移出右末端位的值丢失。对于无符号类型,用 0 填充空出的位置;对于有符号类型,空出的位置用符号位填充
(111001)» 2
(111110)
左移一位,可看作乘以 2;右移一位,可看作除以 2
1.3 大端与小端
1.3.1 什么是大端,小端?
大端和小端是指数据在内存中的存储方式不一样
如 0x123456
大端模式
低地址 | ——> | 高地址 |
---|---|---|
0x12 | 0x34 | 0x56 |
小端模式
低地址 | ——> | 高地址 |
---|---|---|
0x56 | 0x34 | 0x12 |
1.3.2 为什么会有大端,小端?
一开始是因为不同架构的 CPU 处理多个字节数据的顺序不一样,比如 x86 的是小端模式,C51 是大端模式。
后来互联网流行,TCP/IP 协议又规定为大端模式,为了跨平台通信,还专门出了网络字节序和主机字节序之间的转换接口(ntohs、htons、ntohl、htonl)
1.3.3 怎样判断大小端
基本思想是根据数据的截断
通过强制类型转换截断
#include <stdio.h>
typedef enum{
false,
true,
}bool;
bool isBigEndian(void)
{
short num = 0x1234;
char ch = *(char*)#
if(ch == 0x12)
return true;
else
return false;
}
int main(void)
{
bool res = isBigEndian();
if(res == true)
printf("BigEndian\n");
else
printf("SmallEndian\n");
return 0;
}
利用联合体共享内存的特性,截取低地址部分
bool isBigEndian(void)
{
union NUM{
short num_1;
char num_2;
};
union NUM num = {0x1234};
if(num.num_2 == 0x12)
return true;
else
return false;
}
二. GDB
gdb 是一个用来检查逻辑错误的调试工具,语法之类的错误是通过编译器来检查的
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char a[1000];
for(i = 0; i < 1000; i++)
a[i] = -1-i;
printf("%ld\n" , strlen(a)); //值是256,并不是1000;
return 0;
}
1. 进入 gdb
gcc main.c -o run -g
gdb run
2. 退出 gdb
quit(q)
3. 列出源码
list(l)
list 命令一次只能显示 10 行,若想查看后面的源码,可一直按回车键(回车键会重复执行上一次执行的 gdb 命令),直到所有源码显示完
从头查看源码
list(l) 1
查看指定行数的源码
list(l) 5, 10
查看指定函数周围的源码
list(l) main
4. 设置断点 可以在函数名、行号等上设置断点,程序运行后,到达断点就会自动暂停运行。此时可以查看该时刻的变量值,显示栈帧,重新设置断点或者重新运行等。
在指定行设置断点
break(b) line
在指定函数设置断点
break(b) function
查看当前断点信息
info(i) break(b)
5. 运行程序
run(r)
运行直到断点处
6. 查看变量的值
print(p) var
以二进制的形式打印
print(p)/t var
改变内存的内容
print(p) var=value
7. 继续执行断点后续指令
continue(c)
继续执行后续指令,直到遇到下一个断点
8. 下一条指令
会越过函数
next(n)
会进入函数
step(s)
9. 结束当前函数,回到函数调用点
finish
10. 查看变量的类型
ptype var
11. 查看函数参数值
info(i) args
12. 查看局部变量
info(i) locals
13. 查看内存的值
examine(x) /[n,f,u] address
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个单位的内存
f 表示显示格式,t 按二进制格式显示变量,d 按十进制格式显示变量,a 按 16 进制格式显示变量
u 表示单位长度,默认为 4 字节;b 表示单字节,h 表示双字节,w 表示四字节
// 显示一个字节,按二进制格式
x /1bt var
作业
编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串 “”
示例1:
输入: strs = [“flower”, “flow”, “flight”]
输出: “fl”
示例2:
输入: strs = [“dog”, “racecar”, “car”]
输出: ""
解释: 不存在公共前缀