指针的定义
当我们定义传统类型的时候
int a;
short b;
char c;
我们在任何使用的类型名字上面加上星号*就会产生新的类型
int* a;
short* b;
char* c;
int***** a;
short*** b;
float********** d;
My* m;//自定义结构体
...
- 带有的变量类型的标准写法:变量类型 变量名
- 任何类型都可以带* 加上*以后是新的类型
- *可以是任意多个
回顾传统的定义变量的时候
int a;
a=1;
char b;
b=2;
实际上这是一种精简写法
指针的宽度
a=(int)10;
b=(char)20;
int* a;
当我们使用int*的时候,数据的宽度是多少?
char* a=0;
short** b=0;
int*** c=0;
double***** d=0;
My* m = {0};
我们声明了char*,short**,int***等等。。
char* a=0;
00E01E78 C7 45 F8 00 00 00 00 mov dword ptr [a],0
short** b=0;
00E01E7F C7 45 EC 00 00 00 00 mov dword ptr [b],0
int*** c=0;
00E01E86 C7 45 E0 00 00 00 00 mov dword ptr [c],0
double***** d=0;
00E01E8D C7 45 D4 00 00 00 00 mov dword ptr [d],0
My* m = {0};
00E01E94 C7 45 C8 00 00 00 00 mov dword ptr [m],0
宽度始终为4字节;dword;
- 带*类型的变量赋值时只能使用“完整写法”
- 带*类型的变量宽度永远是4字节、无论类型是什么,无论有几个 *
指针加加
a++; b++; c++;
printf("%d,%d,%d", (int)a, (int)b, (int)c);
输出的结果
再次测试
int a = 0;
int* a1 = 0;
int** a2 = 0;
char b = 0;
char* b1 = 0;
char** b2 = 0;
short c = 0;
short* c1 = 0;
short** c2 = 0;
a++; a1++; a2++;
b++; b1++; b2++;
c++; c1++; c2++;
printf("%d,%d,%d\n%d,%d,%d\n%d,%d,%d", a,(int)a1,(int)a2,b,(int)b1,(int)b2 , c, (int)c1, (int)c2);
当int a或者是short a或者是char a的时候,每次加加都会让里面的值加加,从0变成1
当int的时候,每次加加的宽度是int,int a1=0;a1++,a1的值是0,但是a1加加以后是4
结论:
当我们使用int*进行加加的时候,我们每次加加的宽度为int(4字节)
使用char*进行加加的时候,每次加加的宽度为char(1字节)
使用cshort*进行加加的时候,每次加加的宽度为short(2字节)
当星号大于等于2个的时候(int*),无聊星号有多少个(int*****…),无论是char还是short,加加以后宽度永远是4
指针的加减乘除
error C2296: “*”: 非法,左操作数包含“int *”类型
a += 5; a1 += 5; a2 += 5;
b += 5; b1 += 5; b2 += 5;
c += 5; c1 += 5; c2 += 5;
结论:
指针无法使用乘除运算
使用int,short,char进行运算的时候,会对a,b,c里面的值0进行加五的操作
使用int*,short*,char进行运算的时候,a1是int,得到的值,实际上是int或者char去掉一个以后的宽度乘以5,45=20,15=5,25=10
使用int**,short**,char**进行运算的时候,无论加多少,都是4*N
指针间的运算
char* a=(char*)200;
char* b = (char*)100;
int x = a - b;
printf("%d", x);//输出100
结论:
两个类型相同的带类型的变量可以进行减法操作
想减的结果要除以去掉一个的数据的宽度
指针的比较
结论:
带*的变量,如果类型相同,可以做大小的比较
&符号的使用
char a = 10;
short b = 20;
int c = 30;
char* pa = (char*)&a;
short* pb = (short*)&b;
int* pc = (int*)&c;
//简写为
char* pa = &a;
short* pb = &b;
int* pc = &c;
当我们使用一个变量的时候,可以使用&符号来取得变量的地址
char a = 10;
char* pa = &a;
printf("%d", *pa);
当我们使用*pa的时候,可以读取某个地址里面的值
char a = 10;
char* pa = &a;
char** ppa = &pa;
printf("%d", *(*ppa));
当ppa里面存了pa的地址,pa里面存了a的地址
使用*ppa取到的是pa的地址,*pa取到a的地址
char a = 10;
char* pa = &a;
char** ppa = &pa;
char*** pppa = &ppa;
char**** ppppa = &pppa;
printf("%d", *(*(*(*ppppa)))); //10
总结:
带类型的变量,可以通过在其变量前加来获取其指向内存中存储的值
在带类型的变量前面加,类型是其原来的类型减去一个*
使用数组操作指针
char arr[9] = {1,2,3,4,5,6,7,8,9};
char* p = &arr[0]; //取数组第一个元素的地址
char* p2 = arr;
printf("arr[0]---%d\n",*(p+0));
printf("arr[1]---%d\n", *(p + 1));
printf("arr[2]---%d\n", *(p + 2));
printf("arr[3]---%d\n", *(p + 3));
printf("arr[4]---%d\n", *(p + 4));
printf("arr[5]---%d\n", *(p + 5));
printf("arr[6]---%d\n", *(p + 6));
printf("arr[7]---%d\n", *(p + 7));
printf("arr[8]---%d\n", *(p + 8));
取得数组里面的第i个,然后读取
*总结:
&arr[0]代表取数组中第一个元素的地址,可以省略为数组名
(p+i) = p[i]
扩展:
*(p + i) = p[i]
* (*(p + i) + k) = p[i][k]
* (*(*(p + i) + k) + m) = p[i][k][m]
* (*(*(*(*(p + i) + k) + m) + w) + t) = p[i][k][m][w][t]
* () 与[]可以相互转换
int i = 100;
int* p1 = &i;
int** p2 = &p1;
int*** p3 = &p2;
int**** p4 = &p3;
int***** p5 = &p4;
int****** p6 = &p5;
int******* p7 = &p6;
printf("%d\n", *(*(*(*(*(*(*(p7))))))));
printf("%d\n", *(*(*(*(*(*(*(p7 + 0) + 0) + 0) + 0) + 0) + 0) + 0));
printf("%d\n", p7[0][0][0][0][0][0][0]);
函数指针
变量和结构体可以使用指针,函数也可以
在计算机眼里,变量和函数,都是一个变量,有自己的地址
int Add(int x,int y)
{
return x + y;
}
int(*pAdd)(int, int);
pAdd = Add;
int x = pAdd(1, 2);
扩展:小端存储以及int指针访问char数组
int*指针访问char数组已经小端存储使用int指针读出来的数据为什么是反过来的?
代码
#include "stdafx.h"
void fun()
{
char a[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, };
int* p = (int*)a;
printf("%x\n", *p);
printf("%x\n", p[1]);
printf("%x\n", p[2]);
printf("%x\n", p[3]);
}
int _tmain(int argc, _TCHAR* argv[])
{
fun();
return 0;
}