首先是简单的定义基本类型的指针和二级指针的方法
指针就是保存地址的一个变量
#第一篇代码
如何定义指针 以及 * &的理解
#include <stdio.h>
/* 定义一级指针 二级指针 */
int main(void)
{
//定义int char型变量
int num = 1;
char ch = 'a';
//定义int char型指针,指针要和变量类型一致,
//后面写NULL 让他们指向空地址,避免成为野指针
int *num_p = NULL;
char *ch_p = NULL;
//用取地址符号&让指针分别指向num 和 ch 的地址
num_p = #
ch_p = &ch;
//打印指针 *号的作用
//num_p里面放着的是num的地址 *num_p == *(&num), *和&相抵消 得num的值
printf("num = %d\n",num); //打印num的值
printf("num_p = %p\n",num_p); //打印num_p上储存的num的地址 %p用来打印地址
printf("num_p = %d\n",*num_p); //打印num_p解地址之后的值
printf("ch_p = %c\n",ch);
printf("ch_p = %p\n",ch_p);
printf("ch_p = %c\n",*ch_p);
printf("\n");
//二级指针
int **num_pp = NULL;
char **ch_pp = NULL;
num_pp = &num_p;
ch_pp = &ch_p;
//二级指针num_pp里面放着的是一级指针num_p的地址 *num_pp == *(&(&num)), *和&相抵消 得num的值
printf("num_pp = %p\n",num_pp); //打印num_pp上储存的num_p的地址 %p用来打印地址
printf("*num_pp = %p\n",*num_pp); //打印num_pp解地址之后的值,也就是num的地址
printf("**num_pp = %d\n",**num_pp); //打印num_pp解两次址之后的值,也就是num的值
printf("ch_pp = %p\n",ch_pp);
printf("*ch_p = %p\n",*ch_pp);
printf("**ch_p = %c\n",**ch_pp);
return 0;
}
#第二个代码
数组指针和指针数组的区别
数组指针是一个指向数组的指针,通常指向二维数组 可以用来当作一个二维数组的行地址
指针数组则是包含着多个相同类型的指针
#include <stdio.h>
/*数组指针,与指针数组*/
int main(void)
{
//定义一个二维数组
int num[3][4] = {{1,3,5,7}, {9,11,13,15}, {17,19,21,23}};
//定义一个数组指针,也可以称为是数组的行指针。
//将数组指针指向空地址 免得产生野指针
//数组指针的[]内要填写偏移的地址量,例如我们指向的num二维数组
//数组可以看成有三行四列 ,那偏移量就是后面的数字
int (*num_p)[4] = NULL;
//int (*num_p)[4] []中的4表示偏移量
//将数组指针指向num的首元素地址
num_p = num;
//用%p 打印num_p num_p+1 num_p+2的地址
printf("*(num_p+0)的值为 %p\n",*(num_p+0));
printf("*(num_p+1)的值为 %p\n",*(num_p+1));
printf("*(num_p+2)的值为 %p\n",*(num_p+2));
printf("\n");
//打印num_p num_p+1 num_p+2指向的值
printf("**(num_p+0)的值为 %d\n",**(num_p+0));//**(num_p+0) == num[0][0] 的值
printf("**(num_p+1)的值为 %d\n",**(num_p+1));//**(num_p+1) == num[1][0] 的值
printf("**(num_p+2)的值为 %d\n",**(num_p+2));//**(num_p+2) == num[2][0] 的值
printf("\n");
//定义一个指针数组 指针数组就是 数组的元素是由指针组成的
//下面定义一个含有三个int型指针的数组
int *num_pn[3] = { NULL };
num_pn[0] = num; //这里不需要&的原因是因为 数组名本身就代表着整个数组的首元素地址
//但是需要注意 这里的num是一个二维数组 他的首元素是一个整型数组而并非整型变量;
num_pn[1] = num[1]; //这里也不需要&因为num[1]是看作一个数组,名字为地址
num_pn[2] = &num[1][1]; //这里就需要&啦,因为这代指的是一个整型变量了
//打印地址出来 (地址是十六进制数字)
//可以看出num_pn[0]与 num_pn[1]相差 4个int类型,也就是十六个字节
//可以看出num_pn[1]与 num_pn[2]相差 1个int类型,也就是四个字节
printf("num_pn[0]的值为 %p\n",num_pn[0]);
printf("num_pn[1]的值为 %p\n",num_pn[1]);
printf("num_pn[2]的值为 %p\n",num_pn[2]);
printf("\n");
//也可以打印出他们的值来进行理解
printf("*num_pn[0]的值为 %d\n",*num_pn[0]); //输出num[0][0]的值
printf("*num_pn[1]的值为 %d\n",*num_pn[1]); //输出num[1][0]的值
printf("*num_pn[2]的值为 %d\n",*num_pn[2]); //输出num[1][1]的值
printf("\n");
return 0;
}
#第三篇代码
指针的强制转换
通过int类型指针来了解
也可以用其他类型试试
#include <stdio.h>
/*指针的强制转换*/
int main(void)
{
int arr[5] = {1,2,3,4,5};
printf("arr = %p\n",arr);
printf("(int)arr = %x\n",(int)arr);
printf("(int)arr + 1 = %x\n",(int)arr + 1);
//强制转换成整数型指针
/*
int *p1 = NULL;
int *p2 = NULL;
P1 = (int *)(&arr + 1);
P2 = (int *)((int)arr +1);
这样写会弹出
undeclared (first use in this function)
原因可能是因为 没有标准库(c99)
*/
int *p1 = (int *)(&arr + 1);
int *p2 = (int *)((int)arr +1);
//
printf("%x\n",p1[-1]); // 输出 5
printf("%x\n",*p2); // 输出 2000000
/*
大端序
高地址存地位数据,低地址存高位数据
小端序
高地址存高位数据,低地址存地位数据
01 00 00 00
02 00 00 00
得到 00 00 00 02
输出时 为 02 00 00 00
前面的0省略不打印
*/
return 0;
}
#第四篇代码
指针的指向问题
同样以int类型指针为例子
定义指针指向一维数组 和 二维数组的不同之处
#include <stdio.h>
/*int型数组指针,int型指针与数组的指向关系*/
int main(void)
{
int num[5] = {1,3,5,7,9};
int *num_p = NULL;
//当数组前面加上&时它指的是整个数组的元素长度+1
num_p = (&num + 1);
printf("%p\n%p\n%p\n",num_p,(num_p-1),&num_p[-1]);
printf("\n");
printf("%d\n%d\n%d\n",*num_p,*(num_p-1),num_p[-1]);
printf("\n");
//定义一个二维数组
int num_1 [3][4] = {{1,3,5,7}, {9,11,13,15}, {17,19,21,23}};
//定义一个数组指针
int (*num_pp)[4] = NULL;
//定义一个int型指针
int *num_ppp = NULL;
//定义一个int型指针
int *num_pppp = NULL;
//将指针进行指向
num_pp = num_1;
num_ppp = num_1;
num_pppp =(&num_1 + 1); // 数组名在和&或sizeof()一起使用时,代表整个数组,
//加1之后指向数组最后一个元素后面的位置。
//数组指针
printf("num_pp的值为 %p\n",num_pp);
printf("**(num_pp)+1的值为 %d\n",**(num_pp)+1);
printf("*(*(num_pp)+1)的值为 %d\n",*(*(num_pp)+1));
printf(" *(*(num_pp+1)+1)的值为 %d\n", *(*(num_pp+1)+1));
//int型指针
printf("\n");
printf("*num_ppp的值为 %d\n",*num_ppp);
//这个需要注意,并不是指针位移一位,而是先对num_ppp进行解地址,再加一个1
//*num_ppp+1 == *num_1 + 1 == num_1[0][0] + 1
printf("*num_ppp+1的值为 %d\n",*num_ppp+1);
//int型指针 把数组当作成一个一维数组,每次增加一个,地址增加1*sizeof(int)
//*(num_ppp+2) == a[0][2] *(num_ppp+2) == a[2][2]
printf("*(num_ppp+2)的值为 %d\n",*(num_ppp+2));
printf("*(num_ppp+10)的值为 %d\n",*(num_ppp+10));
//指向数组最后一个元素后面的位置的int型指针
printf("\n");
printf("*(num_pppp-1)的值为 %d\n",*(num_pppp-1));
//数组最后一个元素后面的位置 回一位int类型的
printf("*(num_pppp-2)的值为 %d\n",*(num_pppp-2));
//数组最后一个元素后面的位置 回二位int类型的
printf("*(num_pppp-1)也可以表示为num_pppp[-1] %d\n",num_pppp[-1]);
//数组最后一个元素后面的位置 偏移-1位int类型的
printf("*(num_pppp-2) 也可以表示为num_pppp[-2] %d\n",num_pppp[-2]);
//数组最后一个元素后面的位置 偏移-2位int类型的
return 0;
}
#第五篇代码
指针与函数
讲的是一个比较特殊的指针,函数指针
比较特殊的是 函数指针不能通过偏移来定位到下一个函数 会发生段错误
#include <stdio.h>
/*指针与函数*/
//声明函数
int add(int x,int y);
//主函数
int main (void)
{
//定义一个函数型指针
int (*p_fun)(int x,int y) = NULL;
p_fun = add;
//定义两个整型变量
int a,b;
a = 10;
b = 25;
int num_fun = 0;
printf("a = %d b = %d\n",a,b);
//用函数调用的方法调用a+b的函数
printf("函数的调用, bijiao(a,b) = %d\n",add(a,b));
printf("函数的指针调用,(*p_fun)(a,b) = %d\n",(*p_fun)(a,b));
printf("===========================\n");
return 0;
}
int add(int x,int y)
{
x += y;
return x;
}