20170214C语言提升08_指针_01变量及指针及数组
2017-02-14 19:31
435 查看
指针和变量的用法/区别:
1:变量:就是别名,用来访问存储空间2:除了用变量名来访问存储空间,还可以使用指针来访问存储空间。
注意:变量名访问会比指针更加的安全。指针是在变量名无法使用的场合才会用指针。
3:变量名无法使用的场合:
1:局部变量进行参数传递的时候。
2:动态分配内存的时候,局部变量无法实现。
4:指针也是一个变量,指针也有自己的存储空间,指针的变量名也是这块存储空间的别名,指针也会有指针(二级指针)。
5:指针的本质是 保存内存地址的变量。但凡是用到指针,就需要解指针,就是间接访问。
6:使用指针的效率会比使用变量低一些!
#include <stdio.h> int main() { int n = 10; //变量,直接访问 int *pn = &n; //指针,间接访问 n = 100; *pn = 1000; return 0; }//一下问对应的汇编代码。对应的汇编代码为
int n = 10; //变量,直接访问 009113D8 mov dword ptr ,0Ah int *pn = &n; //指针,间接访问 009113DF lea eax, 009113E2 mov dword ptr [pn],eax n = 100; 009113E5 mov dword ptr ,64h *pn = 1000; 009113EC mov eax,dword ptr [pn] 009113EF mov dword ptr [eax],3E8h return 0; 009113F5 xor eax,eax
从汇编代码可以看出,间接访问是先将n的地址放到eax,然后将eax放到pn里面。赋值的时候,变量是一步到位,只用指针的话,回先将pn里面保存的地址取出来放到eax里面,然后才访问赋值。他有一个寻址的过程。可以看出使用变量的效率明显会被指针高一些。
指针本身占用空间!
7:指针和const的结合:
const本身是左结合,左数右址不变!
#include <stdio.h> void foo(int *n) { *n = 100; } int main() { int n = 100; //左数右址,const在*左边代表指针指向的数据为常量,const在*右边代表指针本身值不能改变。 const int *p; //指针指向的值不可变 int const *p1; //指针指向的数据不可变 int* const p2; //指针内部保存的地址不可变 const int * const p3; //指针自己的值和指向的值都不可更改 const int const * const p4; //同上,但是没必要弄这么多const return 0; }
总结:const在*号左边代表里面的数据为常量,在*号右边代表指针本身为常量(不能再指向其他地址)。
数组和指针:
1:数组:相同变量类型的一个集合。2:数组名:数组名和指针很像,使用的时候也有很多相似的地方。大部分地方我们何以将数组名认为是一个常量指针,以下两个场合不一样:
1:sizeof()的时候:指针大小恒定为4,数组名则与数组大小相关。
2:做取地址运算的时候:指针取地址得到的就是指针占用的地址,数组名有两个含义:1:数组的首元素地址,2:数组的地址。对数组名取地址得到的就是数组的地址,还是数组的首地址。所以对于 数组名和数组名取地址,两个得到的是一样的,但含义不一样。对两者进行+1,++等操作的时候,两者不一样,数组名++带有类型,数组名取地址之后的++加的大小为数组大小。
#include <stdio.h> int main() { int array[10] = { 0, 1, 2, 3, 4, 5 }; int *parray = array; //数组的首地址 int *paddarray = &array; //数组的地址 //warning C4047: “初始化”:“int *”与“int (*)[10]”的间接级别不同 printf("%p\t%p\t%p\t%p\n", parray, paddarray, parray + 1, paddarray + 1);//前两个相同,后两个都是+4 printf("%p\t%p\t%p", array, array + 1, &array + 1);//前者+4,后者+40 //array + 1 = array + sizeof(*array) //计算方式 //&array + 1 = &array = sizeof(*&array) return 0; }
对于二位数组也是一样的!上代码:
#include <stdio.h> int main() { char carray[100] = { 0 }; //元素大小是1,数组大小是100; //首元素地址偏移的时候是+1byte,数组偏移的时候是+100byte。 char ccarr[100][100] = { 0 }; printf("%p\t%p\t%p\t%p\t%p\t%p\n", ccarr, ccarr + 1, ccarr[0][0] + 1, ccarr[0] + 1, &ccarr[0] + 1, &ccarr + 1); // 首地址,首地址+100,第一个值+1, 首地址+1, 首地址+100, 首地址+10000 return 0; }
3:数组是直接访问,指针是间接访问。
//other.c里面的内容 char *pstr = "I Love Mark"; //main.c里面的内容 #include <stdio.h> extern char pstr[];//欺骗编译器说是一个数组,实际为一个指针 int main() { printf("%s\n", pstr);//打印出乱码,这里是直接把pstr按char*的方式访问。打印出的是字符串的地址(但是是按char*,所以是乱码)。 printf("%s\n", (char*)(*(unsigned int*)pstr));//打印I Love Mark return 0; }//后面的方法为强转为指针,解指针后按char*打印。
4:两个指针之间的运算: 指针-指针:计算出来为地址偏移量,结果可正可负,带类型。可以用循环对内存空间进行遍历。 指针+指针:出错!指针间不可相加。 指针=指针 指针!=指针:比较的是指针保存的地址。也是在连续空间才有意义。注意:指针运算一般为连续内存空间内的操作。如果任意不相干的两个指针来运算是没有意义的,可以通过编译并得出结果,但结果是未定义的。和对野指针操作差不多,无意义的。
5:使用指针来访问数组的效率要大于只用下标来访问:
一般为比较老的代码才有,现在的编译器优化很多,实际两者速度差不多(Debug下指针快,Release下一样)。
#include <stdio.h> int main() { int array[] = { 1, 2, 3, 4, 5 }; int *parray = array; array[3] = 5; printf("%d", array[3]); *(parray + 3) = 5; printf("%d", *(parray + 3)); return 0; }
Debug下的部分汇编代码为
array[3] = 5; 00E03C51 mov eax,4 00E03C56 imul ecx,eax,3 00E03C59 mov dword ptr array[ecx],5 printf("%d", array[3]); 00E03C61 mov eax,4 00E03C66 imul ecx,eax,3 00E03C69 mov esi,esp 00E03C6B mov edx,dword ptr array[ecx] 00E03C6F push edx 00E03C70 push 0E05868h 00E03C75 call dword ptr ds:[0E09114h] 00E03C7B add esp,8 00E03C7E cmp esi,esp 00E03C80 call __RTC_CheckEsp (0E01136h) *(parray + 3) = 5; 00E03C85 mov eax,dword ptr [parray] 00E03C88 mov dword ptr [eax+0Ch],5 printf("%d", *(parray + 3)); 00E03C8F mov esi,esp 00E03C91 mov eax,dword ptr [parray] 00E03C94 mov ecx,dword ptr [eax+0Ch] 00E03C97 push ecx 00E03C98 push 0E05868h 00E03C9D call dword ptr ds:[0E09114h] 00E03CA3 add esp,8 00E03CA6 cmp esi,esp 00E03CA8 call __RTC_CheckEsp (0E01136h)
Release下的汇编代码为
array[3] = 5; printf("%d", array[3]); 00C21000 push 5 00C21002 push 0C22100h 00C21007 call dword ptr ds:[0C22090h] *(parray + 3) = 5; printf("%d", *(parray + 3)); 00C2100D push 5 00C2100F push 0C22100h 00C21014 call dword ptr ds:[0C22090h] 00C2101A add esp,10h
6:数组名当作参数传递的时候,会降级为指针。相当于传递的指针,是做的copy,在子函数里面可以改变这个参数,对外面没有任何影响。
#include <stdio.h> int foo(int **array)//指针的指针 { int n = 10; *array = &n;//修改了数组里面的值,一般不会这么写,会有警告。 return n; } int main() { int array[] = { 1, 2, 3, 4, 5 }; foo(array); printf("%p", array); return 0; }
相关文章推荐
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- C语言字符串指针变量与字符数组的区别
- 浅谈C语言中变量、常量、数组、字符串、指针的地址
- C语言学习笔记(6)-如何从变量声明的表面上来区分指针数组和数组指针