8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
环境准备
Ubuntu 操作系统、VIM 编辑器、GCC 编译器、GDB调试器。
初始指针
通过两个数的交换引入指针指针的概念。
swap(int a, int b);
swap(a, b);
swap(int *a, int *b);
swap(&a, &b);
gdb 调试工具的使用
分析原理、分析结果。
使用 gdb -help 检查电脑是否安装。
源程序用于调试:gcc -g main.c -o main.out
使用 gdb 调试:gdb ./main.out
gdb 一些常用命令:l :列出当前软件项目源代码
enter:继续执行上一条命令
break 12:断点打在 12 行
start:开始调试,默认断点在 main 函数的入口处
p a:打印变量 a 的值
n:执行下一行
s:进入一个函数的内部
bt:查看函数堆栈
f 1:切换函数栈
q:退出调试
指针与内存
计算机中的数据表示方法:
计算用二进制,显示为十进制,编程用十六进制。
内存管理:
内存是什么?内存是由操作系统统一管理。
1 Byte= 8 Bits
插两根 2G 内存条 <=> 插一根 4G 内存条,计算机中操作系统把内存看成是一个整体来计算内存的大小。
内存条不是你想插多少就插多少的,32 bit 的操作系统最大使用 4G 内存。32 位计算机的地址总线是 32 位的,也就是寻址空间是 32 位。
32 位指的是:给内存编号只能编到 32 个二进制位。
地址总线可以存在多种状态,32 根总线就有 2^32 个状态。2^32 B = 4GB 。 4G 的内存是远远不够用的,所以现在 64 位的操作系统更为流行。操作系统会对所有的内存进行编号,每个编号对应唯一的内存字节地址。
内存都要交给操作系统来管理。一个计算机中可能同时要运行多个程序, 要由程序员来对内存直接进行管理是不太合理的,内存的占用不稳定。 内存之中有一个部分内存空间是给操作系统内核使用的,操作系统内存和用户内存隔离开的好处:操作系统的内存不会被大量占用
避免机器卡住、卡死、死机等状态
可通过操作系统把应用程序关闭
使操作系统更安全
C 语言代码被编译之后存到磁盘,运行时编译后的二进制数据加载到内存中,代码段。声明一些全局变量或者声明一些变量,这些通常放在数据段。
C 程序在内存中布局文本(代码)段
初始化数据段
未初始化(bbs)数据段
堆
栈
文本或代码段:Text or Code Segment
也叫做代码段。顾名思义,该段存储包含已编译程序的机器代码,通常是只读段,用于防止程序被意外修改。
初始化数据段:Initialized Data Segment
初始化数据存储预先初始化的所有 global, ` static,const和外部变量(extern` 关键字声明)。
还会因为 const 而细分为可读可写区域和只读区域。
#include
char str1[] = "Hello"; // 全局变量存储在数据段的可读可写区域const char str2[] = "World"; // 存储在数据段的只读区域
int main()
{
static int a = 0; // 静态变量存储在数据段 return 0;
}
未初始化数据段:Uninitialized Data Segment (bss)
#include
char c; // 未初始化变量存储在未初始化数据段
int main()
{
static int i; // 未初始化静态变量存储在未初始化数据段 return 0;
}
通常,初始化数据段和未初始化数据段统称为数据段。
堆
堆是通常发生动态内存分配的段。在 C/C++ 中,当需要使用 malloc / calloc / new 函数分配更多内存时,堆会向上增长。
#include int main()
{
char *p=(char*)malloc(sizeof(char)); // 内存分配在堆段 return 0;
}
栈
栈段用于存储所有局部变量,用于将参数传递给函数以及函数调用结束后要执行的指令的返回地址。局部变量具有定义它们的所在函数块的范围,它们是在控制进入所在函数块时创建的。所有递归函数调用都添加到内存的栈中。
变量和指针的本质:C 语言语法是不允许我们直接操作代码段的。
变量的本质是什么?变量名它只是一个代号
变量的本质就是内存
int *pa = &a;
(gdb)p pa与 p &a 得到的结果相等
(gdb)p &pa打印 pa 的这个变量自己的地址
C 语言中所有的变量都有类型:int 类型就保存整数
double 类型就保存双精度的浮点数
那么指针保存的是什么呢?指针保存的就是内存地址
操作系统对内存的管理
32 bit :指针是 4 Byte
64 bit:指针是 8 Byte
代码段是由低地址向高地址分配的,先声明的函数地址小,后声明的函数地址大。而栈刚好相反,
函数栈以及数据段内存
静态变量在数据段里面的一个固定的位置。
函数指针与指针指向的数据访问
函数指针的声明语法。
char (*pf)(int);
// pf指向一个函数。*pf是一个函数指针
// char是函数的返回值
// int是参数的类型
字符串和数组
数组申明的内存排列
*(p + i) 等同于 p[i]
gcc 编译器的自动优化,会把同一类型的变量放在一起。
指针运算
++ 先判断数据的类型,然后再往下移,如 int 类型,则移 4 个字节。
int array[3];
int *pa = array;
pa 是一个可以指向不同地址的指针变量。
array 本质上是一个指针常量。
指针常量能做的事情,指针变量是一定可以做的,但是反过来就不行。
数组和指针有一定的相同点,已有一定的差别。
字符数组和指针字符串
#include
int main()
{
char str[] = "hello";
char *str2 = "world";
char str3[10];
printf("input the valuen");
scanf("%s", str3);
printf("str is %sn", str);
printf("str2 is %sn", str2);
printf("str3 is %sn", str3);
return 0;
}
// ➜ Desktop ./a.out
// input the value
// hello
// str is hello
// str2 is world
// str3 is hello
str2 在代码段,是不可以再进行写入操作的。栈内存和堆内存都是可以被写入的。