Linux与数据结构 2019-1-31

今天是将之前学过的东西进行简单的复习。

1. # 的含义

# 代表预处理,预处理的主要功能是进行替换。

2.include的尖括号与双引号

include<>的搜索范围比之于include""的搜索范围要小:尖括号的搜索范围是系统内部的库,而双引号则包括用户自定义的库以及系统的自带库。

3.主函数的参数

一般来说,主函数 main 函数是具有参数的,但是一般可以进行省略,主函数的参数是main(int argc, char** argv),其中的argc代表的是输入参数的个数,argv则代表了输入的参数的内容。

4.主函数的return

主函数的return表示程序正常退出。

5.基本数据类型

5.1 基本数据类型:

int,long,char,short,double,float。

5.2 char类型:

1 个字节,可代表数的范围为 -128~+127

5.3 short类型:

2 个字节,可代表数的范围为 -32768~+32767

5.4 int类型:

4 个字节,可代表数的范围为 -2147483648~+2147483647

5.5 long类型:

4/8 个字节(根据操作系统的位数所改变:32位系统下占4个字节,64位系统下占8个字节)。

5.6 float类型:

4 个字节,可以表达小数点后6位的小数。

5.7 double类型:

8 个字节,可以表达小数点后15位的小数。

6.例题

例:

char a, b, c, d;
a = 30;
b = a++;
c = ++a;
d = (a++)*10;

求d的值为多少?
解:a = 30;b = a++ = 30,a = 31;c = ++a = 32,a = 32;d = (a++)*10 = 320,但是由于char类型的范围是 -128~+127,故d的值为64。

==============================================

7.例题

例:int i = -2147483648,则-i、~i、1-i、-1-i分别是多少?
解:由于负数在计算机中的存储方式是以补码形式存在的,因此i在计算机的存储为:1000 0000 0000 0000 0000 0000 0000 0000,故-i的意思是先将======================;i则是取除符号位外所有位数的反,因此i = 2147483647

8.有符号向无符号类型提升问题

例:int a = -5,unsigned int b = 1;a+b会使得a向无符号类型提升,因此结果会大于5。

9.例题

例:char a = -2;int b = 5;此时将a的前24位补零,因为会进行类型的提升。

10.sizeof是一个运算符,不是一个函数,其结果的类型是size_t类型,使用sizeof的结果与int类型的数值进行计算也会发生类型的转换。

11.例题

例:int i = 2;int j = 5;i+++j的值是多少?
解:该题相当于(i++)+j,因此值为7,其中的知识是++是左结合的,因此会先结合i,则对于j只剩下一个+,故结果为7。
另:对于 ++i++,编译器会报错:不是可修改的左值。

12.switch语句

12.1 switch后只能放整型的变量或常量。

12.2 case后只能放整形常量或常量表达式。

13.循环的效率问题

for、while的效率相同,do while的效率更高一点,因为其是汇编指令。

13.1 例题

例:int k;for(k;k=0;) 执行的次数?
解:为零。因为k=0是一个常量表达式,其返回值是0,因此该循环一次也不执行。

13.2 短路原则

例:m = 5;n = 1;–n&&m++的值?
解:为零。因为当n为1时,–n的值为0,因此&&后的m++不会执行,故该答案为零。

14.内存操作

14.1 读、写、取地址,取地址的符号是 &。

14.2 内存操作的基本大小是:字节。

14.3 访问内存的方法:直接访问和间接访问(直接访问:指针,间接访问:二级指针)。

14.4 指针在函数中的使用

1.下列程序无法正常执行,请找出其原因。

void func(char* p)
{
	p = (char*)malloc(sizeof(char*));
}

int main()
{
	char *p = NULL;
	func(p);
	strcpy(p, "hello");
}

解:其原因是因为func中的p和main中的p不是同一个p,func中的p在func§;之后就被回收,并没有传递给main里的p,因此main里的p仍旧是NULL,故无法进行strcpy操作。
解决方法:在写func函数时进行二级指针的传入,即func(char** p)。

2.下列程序可以正常执行的原因:

struct
{
	int a;
	char *p;
}s;
void func(s* q)
{
	q->p = (char)malloc(sizeof(10));
}
int main()
{
	s* q = (s)malloc(sizeof(s));
	func(q);
	strcpy(q->p, "hello");
	return 0;
}

解:因为对于结构体s来说,其中的成员p在创建了结构体后就是存在的,因此当进行func函数时,其中的p就被申请了空间,因此可以进行strcpy操作。

14.5 内存共有5个区

1.堆区(都能进行存放);
2.栈区(存放局部变量和函数入口地址);
3.字符常量区(存放数字和字符串,只能访问,不能修改);
4.全局区(又称静态区,存放全局变量作用于整个项目和静态变量作用于定义文件);
5.代码区(存放代码)。

14.6 堆区和栈区的区别

1.申请方式不同:栈区由系统分配回收,堆区由使用者分配回收,不回收则会导致内存泄漏;
2.申请效率不同:栈连续但是堆不连续(堆区有一个存储地址和大小相同的链表,申请时需要进行遍历链表);
3.生命周期不同;
4.存储内容不同;
5.生长方式不同:栈区向下分配,堆区向上分配;栈区分配的变量地址逐渐减小,堆区分配的地址逐渐变大;
6.堆区会产生内存碎片。

15.数组

15.1 由类型相同且空间连续的元素组成。

15.2 动态申请数组:int p=(int)malloc(sizeof(int*))。

15.3 数组名,代表数组的首元素的地址。

15.4 例题

例:int a[5] = {1, 2, 3, 4, 5};*(&a+1)无法运行,原因?
解:由于a是数组的首地址,&a表示这个数组的地址,因此&a+1会向后偏移5个int的大小,故无法取到5的后面的那一位,因此会出错。

15.5 例题

例:int a[5] = {1, 2, 3, 4, 5};((int)&a+1)的值?
解:值为2。因为&a为数组地址,但是(int*)将其强转为int*类型的,因此+1之后变为2的地址,在间接寻址得到2。

15.6 例题

例:int a[5] = {1, 2, 3, 4, 5};((int)((int)&a+1))的值?
解:值为0x02000000。原因:默认在计算机中存储的方式是小端存储(低字节存在低地址)。

猜你喜欢

转载自blog.csdn.net/weixin_42896619/article/details/88187331