if else的代码是一个条件一个条件进行比较的。
下面看switch的汇编执行情况
int a=8;
switch(a){
case 1:
printf("正确1");
break;
case 2:
printf("正确2");
break;
case 3:
printf("正确3");
break;
case 4:
printf("正确4");
break;
case 5:
printf("正确5");
break;
case 6:
printf("正确6");
break;
case 7:
printf("正确7");
break;
default:
printf("buzhengque");
break;
}
汇编代码为:
当条件少的时候可以从其中看出来,下面switch的汇编代码过程也是一个一个进行比较的:
在switch中有点是空间换时间的事,在switch中它是先把选择的值进行在内存中存储,在调用函数的时候就会预先把选择条件中要运行的程序现在内存中分配好空间,在通过计算在直接找到相应的位置,单在if else就不是这样它是先一个一个遍历,在不匹配的条件下是不对不匹配的内容进行内存的分配的。
switch用一段合理的空间去换取结果的计算。
探讨switch的底层优化情况选择。
在选择的条件中的选择项在中等的情况下的情况下:
当在选择的条件中的选择数是在稍微中等偏上的情况下:
dwdaord汇编中意思是直接连续取四个字节,32位的电脑是一次是4个字节,4个字节连续存储,一个字等于两个字节,一个字节等于8位,并且每次取址的时候都是选取字节的首地址进行取址的。
【】是指取地址中的地址;
call 是调用的意思;
ALT + J是转换成汇编;
F10 是调试,F11 是跳进方法里;
栈空间是系统不断覆盖读写的而不是来回清除掉的,就像我们的回收站机制一样,不存在释放,
在栈顶指针esp使用的时候,出现个这句代码汇编:
pop eax:
1、函数返回变量值
此时,返回变量值的方式与函数调用传值同样的道理,在函数结束返回时,将局部变量值拷贝给一个临时变量,然后将这个临时变量返回给调用函数。因此,即使局部变量在返回时已经释放内存,也不影响返回的变量值。
复制代码
1 int test_func()
2 {
3 int i = 2;
4 printf("Function i : %d\n", i);
5 return i;
6 }
7
8 int main()
9 {
10 int a = 0;
11 a = test_func();
12 printf("Main Now: %d\n", a);
13
14 return 0;
15 }
从汇编的角度来看源代码:
由以上看出:返回变量值的时候,直接将局部变量的值传给了了寄存器eax。
2、函数返回地址
此时注意:C语言的指针操作,大部分都是直接对指针指向的变量直接操作,函数内部的变量和指针一般分配在栈上,而栈上的数据(空间都是覆盖使用的),
int *test_func()
2 {
3 int local_data = 10;
4
5 printf("Function local_data : %d\n", local_data);
6
7 return &local_data;
8 }
9
10 int main()
11 {
12 int *main_data = NULL;
13
14 main_data = test_func();
15
16 printf("Return data: %d\n", *main_data);
17
18 return 0;
19 }
从汇编语言角度查看源码:
由以上看出:返回指针的时候,用的是指令lea,这条指令的作用是,将[ebp-4](此单元对应的是变量local_data在栈上的数据存储位置)这个数据单元的地址传给eax寄存器。
在这上面可以就看出下面的代码返回的是一个整数的地址,但在main方法中却可以直接
&a是取址,*a是取址中的值,所以在a中只能是赋予地址,赋予其他的值就会出错:
但上面的结果说明在调用函数的时候,在栈中数据不是被释放,而是在以后会被覆盖的,但最好不要这样用这样会出现野指针,当函数入栈的时候,里面有局部变量,就会直接定义后在有个栈顶指针会往下走,当在有数据的时候会有覆盖之前的数据,要是没有覆盖原来的局部变量当然也会打印出来,但当局部变量覆盖掉后就会形成一个不知所踪的值赋给指针变量a了。
&(p+0)是指取出是0x666,数组本身就是指针,对于&,数组取的是堆中的地址,基本数据类型取得的栈中的地址
什么是指针呢?
系统为每一个内存单元分配一个地址值,C/C++把这个地址值称为“指针”。如有int i=5;,存放变量i的内存单元的编号(地址)&i被称为指针。
“指针变量”则是存放前述“地址值”的变量,也可以表述为,“指针变量”是存放变量所占内存空间“首地址”的变量(因为一个变量通常要占用连续的多个字节空间)。比如在int i=5;后有一句int *p=&i;,就把i的指针&i赋给了int *型指针变量p,也就是说p中存入着&i。所以说指针变量是存放指针的变量。
有一个事实值得注意,那就是有不少资料和教科书并没有如上区分,而是认为“指针是指针变量的简称”,如对int *p=&i;的解释是:声明一个int *型指针p,并用变量i的地址初始化;而严格说应该是声明一个int *型指针变量p才对。所以有时看书要根据上下文理解实质,而不能过于拘泥于文字表述。
(1) ”指针“是概念,“”指针变量“是具体实现,指针也是一个变量,所以也需要进行定义,而对于指针的定义,与一般变量一样。
(2)一个变量的(内存)地址称为该变量的”指针“,通过指针变量能找到以它为地址的内存单元。而指针变量是用来存放另一个变量的地址的(即指针),并且指针变量有且只能存放地址。
1,指针就是地址,地址就是指针
2,地址就是内存单元的编号
3,指针变量就是存放内存地址的变量,不能存放其他的数据。
这也就是说
内存地址是内存当中存储数据的一个标识,并不是数据本身,通过内存地址就可以找到内存当中存储的数据。
基本概念:1BYTE=8bit
地址总线:CPU通过地址总线来指定存储单元。
总线决定着cpu所能访问的最大内存空间大小。
地址总线是地址数量之和。
内存地址是一种用于软件及硬件等不同层级中的数据概念,用来访问电脑贮存中的数据。
内存地址只是一个编号,代表着一个内存空间。这个空间不会随着编号中的位置改变的,一个内存地址所代表的永远就只是一个字节,内存中每个字节都会有一个编号,16位,32位只是这个编号的长度,不会影响内存的最小单元大小。
所以这个16位的cpu,所有表示的地址个数是2^20 = 1048576个,一个地址所指大小1个字节 ,也就是1M;
32位的cpu,所有表示的地址个数是2^32 = 4294967296个,一个地址所指大小1个字节 ,也就是4G;
总结
内存地址只是一个编号,代表一个内存空间;
内存地址所执行的内存单元大小就是1字节,跟内存地址位数无关;
内存空间大小就是寻址能力,即能访问到多少个地址
也就可以说在主内存的地址标号是固定的,里面的内存中的东西可以是数据也可以是地址,就如上面的栈指向堆中的数据一样。也可以是在方法区中,每一个函数的头都是代表着一个函数在方法区的地址,则在调用时候是在栈中调用的是地址,所以储存在栈中的是方法的地址,在去由地址在去找在方法区中的函数。