20170214C语言提升08_指针_01变量及指针及数组
来源:互联网 发布:js表单验证表示时间 编辑:程序博客网 时间:2024/06/07 18:43
指针和变量的用法/区别:
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 [n],0Ah int *pn = &n;//指针,间接访问009113DF lea eax,[n] 009113E2 mov dword ptr [pn],eax n = 100;009113E5 mov dword ptr [n],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;//同上,但是没必要弄这么多constreturn 0;}
数组和指针:
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);//前两个相同,后两个都是+4printf("%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, 首地址+10000return 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 Markreturn 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;}
1 0
- 20170214C语言提升08_指针_01变量及指针及数组
- 20170215C语言提升08_指针_02数组指针及指针数组及函数指针
- 9、C语言中二维数组及数组名及指向二维数组的指针变量
- C语言中“指针”和“指针变量”区别及定义
- C语言学习之数组及指针
- c语言 数组及指针部分
- C语言_函数指针数组指针
- 指针及指针变量
- C语言数组名及指向数组指针的小结
- C语言_数组与指针
- C语言二维数组的指针及首地址问题
- 1.6 C语言内数组及指针的使用
- C语言中指针,数组,字符串及函数
- C语言_为什么字符串可以赋值给字符指针变量,字符串的属性及存放位置
- 指针数组及数组指针
- C语言_指针
- C语言_指针
- C语言_指针
- JSPath使用汇总
- sublime text 配置本地静态服务器方法
- 关于图像目标检测的HOG\LBP\Harr特征的博客
- vmware12中安装winxp
- go语言学习之----读取配置文件的方式toml
- 20170214C语言提升08_指针_01变量及指针及数组
- 欢迎使用CSDN-markdown编辑器
- IPC-Messenger使用实例
- Java实现几种常见排序方法
- Spring security下csrf token的认证
- 淘宝技术这十年
- Spring cloud Eureka服务注册及发现(二)创建注册服务
- 新建服务器的相关开发配置-----jdk配置
- MYSQL 修改密码