OS-C语言基础

Posted by BUAADreamer on 2021-03-30
Words 1.1k and Reading Time 4 Minutes
Viewed Times

近期操作系统课上测试因为C语言的薄弱基础接连受到暴击,笔者痛下决心一定要开始一篇C语言基础总结的博客,时间有限,本次先将OS两次课上的坑总结一下,以后再补充其他的。

数据类型与移位运算·

unsigned int 是无符号整数

int有符号整数

对上述两者赋值时,都是将右边的数字的补码存入相应地址中。

比如:int a = -1;unsigned a = -1;其实这两个a存的变量内容一样,都是FFFFFFFF(负数的首位为1不变,其他位取反然后整体+1.)

上述两者如果用%d输出,都会输出一个-1,但是如果输出一个%u则会输出32位无符号整数。另外,%o是8进制,%x是输出十六进制

同理对于其他的char/unsigned char long/unsigned long等。

同时,在C语言中默认为十进制数字,可以直接用0x开头表示十六进制,0开头表示8进制,0b开头表示二进制数字。如:0x1af 0176 0b101

同时建立起一个意识就是OS课中C语言中的最小单位可以认为是char,即一个字节

大小端转换·

那么再有了移位的运算符知识我们就可以实现lab1-1课上的Extra的大小端转换问题了。

大小端是针对字节来说的,对于一个数字0x12345678来说下图是一个小端存储

1
2
3
           -------------------------------------
首地址0x4000|00010010|00110100|01010110|01111000|末尾地址0x4004
-------------------------------------

而这张是一个大端存储

1
2
3
           -------------------------------------
首地址0x4000|01111000|01010110|00110100|00010010|末尾地址0x4004
-------------------------------------

即每个字节内其实都是按照所谓的"小端存储",而大端存储相当于是把小端存储的字节序列倒序排列了。

一般的x86/ARM架构其实都是小端存储为主,但是也时常有解析大端存储数据的需求。

有了这些就可以进行转换了。

1
2
3
4
5
6
7
8
int a1 = 0xff<<24;
int a2 = 0xff<<16;
int a3 = 0xff<<8;
int a4 = 0xff; //本来以为必须要定义成unsigned,结果其实不用也可以
int a = 0x12345678;
//注意优先级,可以输出一下这个看看 a = (a << 24) & a1 + (a << 8) & a2 + (a >> 8) & a3 + (a >> 24) & a4; 结果为0
a = ((a<<24)&a1) + ((a<<8)&a2) + ((a>>8)&a3) + ((a>>24)&a4);
// a = 0x78563412

一旦遇到移位运算符,逻辑运算符,多加括号是个好习惯。

指针与结构体·

sizeof(type) 返回该变量所占字节数

指针本质上可以理解为一个int型变量,存着一个32位的地址数据,因为有内存里其他数据的辅助,可以解析相应地址的变量。

而数组和指针没有本质区别,即如下面所示

1
2
3
4
int a[4]={1,2,3,4};
int *b=a;
printf("%d",a[1]);
printf("%d",b[1]);//b[1]和*(b+1)一样

结构体的基本使用方式回顾

1
2
3
4
5
6
7
8
9
10
11
12
struct s1 {
int a;
char b;
char c;
int d;
};
struct s1 t1;
t1.a=12;t1.b='a';t1.c='b';t1.d=10;
struct s1 * t1p = t1;
t1->a=13; //指针需要使用箭头的引用方式
struct s1 * tp = (struct s1 *) addr;//将一个地址转换成结构体指针
struct s1 t = *((struct s1 *) addr);//将一个地址转换成结构体变量

值得注意的是结构体内会很贴心的(一个哥们直接被这个坑了,挂了一次课上)将第二个b/c这两个char变量放在a变量后的连续两个字节里,然后空两个字节之后继续存d变量。即是下图这样的(一个*代表一个字节)

1
2
aaaabc  dddd
************

所以第二次课上如果想直接使用寻找四个变量的地址的方式,就应该先加一个sizeof(int)得到b,再加一个sizeof(char)得到c,再加两个sizeof(char)得到d

而笔者则是采用了直接将得到的变量利用结构体指针强制转换成结构体变量再进行使用的方式,但是课上测试时,在输出结构体变量内的数字时没有对符号进行清零导致了错误。