二级指针,数组指针,指针数组和函数指针

二级指针

二级指针就是指向一级指针的指针,二级指针里面存放的是一级指针的地址

一般前情况下定义为

int *p=&a;

int **q=&p;

二级指针指向一级指针,一级指针指向变量a

那么关于二级指针的使用也和一级指针相同,在不加限定条件下的情况下可以通过二级指针进行两次解引用访问一级指针指向的变量的值;

**q=10;

但是普遍的情况是会对 二级指针在定义上出现限定

例如 const与二级指针的结合,上一节我们对const和一级指针的结合有了了解,现在我们来了解const和二级指针的结合

例如在这里,我们对每一行代码进行分析,用const修饰后的部分可以看作常量,也就以为着不能对它进行操作。

const int *p;用const修饰了*p,也就意味着我们不能通过解引用来修改p指向的变量的值,但是可以改变它的指向,所以*p=10;错误  p=&b;正确

int *const q;用从const修饰了p,也就是说可以用*p来修改指向变量的值,但是不可以改变它的指向

const int **s;同理,不能进行二级解引用,但是可以改变它的指向

int*const*t;不能改变指向,但是可以解引用

const  int *const*z;这里是const修饰了**z和*z,这意味着即不可以解引用也不能改变指向

这是一般的情况,那么如果再特殊一点,a和b都用const修饰,那么该做出怎么样的修改

a,b都用const修饰,那么不管是间接或者直接修改a,b的值的语句都是错误的,在定义指针时也要注意,如果用普通的一级指针或者二级指针定义,那么必然就可以通过解引用来对a,b值进行修改,但是前提是a,b的值不能进行修改,因此出现矛盾,所以在这种情况下,定义时一定要用const修饰*q和**t,那么*t需不需要进行const修饰则根据场景进行修改即可。

数值指针

定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针

这里可以看到arr和&arr[0]都是一样的,括号表示这里侧重的是指针,都表示的是第一行首元素的地址,如果对p进行加一操作,那么指针就会指向到第二行首元素的地址,所以p+1后,增加了四个int

那么要一个一个的访问二维数组的元素,就要定义为int*s=&arr[0][0],这样s+1就会一个一个的访问二维数组的每一个元素

    int (*p)[4] = arr;
    //p++;  p + 4个int   
    int(*q)[4] = &arr[0];
    //q++; q + 4个int
    int* s = &arr[0][0];
    //s++; //s + 1个 int
    int (*w)[3][4]= &arr;
    //w++; //w + 12个int

指针数组

数组元素全为指针的数组称为指针数组。

一维指针数组的定义形式为:"类型名 *数组标识符[数组长度]"。

例如,一个一维指针数组的定义:int *ptr_array[10]。

比如    const char*arr[5]={"hello","world"}

然后访问这个数组 char*p=arr[0],那么这里arr[0]就代表了数组首元素的地址,即”hello“

那么我们想访问hello中的h又该如何访问呢,这里我们可以用

const char* str[2] = {"hello","world"};
    const char** p = &str[0];
    printf("%s\n", *(p + 1))

这里就可以访问到

函数指针

	int add(int a, int b) {
	return a + b;
    }
    int mul(int a, int b) {
 	return a * b;
    }
    int main(){
     int a, b;
	char op[10] = {0};  //"+"  "*"
	scanf("%d%d",&a,&b);
	scanf("%s", &op);
	//定义一个函数指针,指向add  指向mul
	int (*pfun)(int, int); 
	//声明一个指针变量
	// 函数指针类型
	if (strcmp(op,"+") == 0) {
		pfun = add;
	}
	else {
		pfun = mul;
	}
	int result = pfun(a, b);
	printf("%d\n",result);
    }

这里就可以看到函数的参数类型相同,返回值类型相同,就可以用一个函数指针指向函数,这就是函数指针

typedef

这个的作业的是函数重命名

例如

int *p,q;

那么这个时候的p,和q分别是什么类型的变量呢,其实p是指针变量,q是int类型的变量

那么我们可以使用宏

#define point_32 int*

但是这个宏只在预编译环节起作用,其实还是没有作用

这个时候我们就可以使用typedef

typedef  int* point_32意思是将int*重命名为point_32

那么在下面就可以使用

point_32 p,q

那么p,q就都是指针变量

scanf函数的缓冲区

在刚刚的函数指针中

int a, b;
	char op[10] = {0};  //"+"  "*"
	scanf("%d%d",&a,&b);
	scanf("%c", &op);

如果在这里将a,b,op输出出来,就会发现输出a,b后程序就会结束

这是因为输出a,b回车后,系统无法识别这个回车是op还是换行动作,就会出现这个情况

解决方法是输入完整形之后,再进行一个字符\n的获取,获取后不用(目的是将其从缓冲区中剔除,继而获得下一个有效数据)

可以这样解决

scanf("%d",&a);

scanf("%c",&num);//一般使用getchar()

scanf("%d",&c);

或者使用其他函数

putchar()

getchar()

gets()

puts()

在输入输出字符串的时候我们就可以使用这些函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值