指针知识详解

i前言

1.定义:指针是以内存地址为值,通过该地址能直接或者间接寻到所需的内存单元。
2.c语言之所以强大,以及它令人着迷的自由性和灵活性,主要来源于指针。
3.指针的用途:
(1)指针允许程序员以更简洁的方式引用大规模的数据结构。数组就是一种较大的数据结构,它由多个数据构成,对数组元素的引用就是由指针来实现的,而数组名本身就是一个指针。
(2)指针允许程序的不同部分能够共享数据。——函数之间的传址传值。
(3)利用指针,能够在程序执行过程中预留新的内存空间。——动态获得内存空间。
(4)指针可以用来记录数据项之间的关系。
(5)指针可以引用函数,将函数作为参数进行传递。

1 指针变量的声明和初始化

1.1指针变量的声明

(1)形式: 类型 * 指针变量名;
(2)指针变量的大小取决于电脑是32位还是64位:
32位的是4个字节;64位的是8个字节。
(3)指针变量的写法举例:int *p;

1.2指针变量的初始化

注意:指针初始化很重要,否则变量会变成野指针变得很危险,而且此时指针指向的任意的地址而编译器不会报错。
(1)int *p=NULL;
(2) int i;int *p=&i;

2 指针变量的使用

2.1通过指针访问变量

int i; int *p=&i;
i=0; 和 *p=0;等价

2.2 指针变量的地址

指针变量存的是地址,而本身在内存上占一个空间,也是一个地址。

2.3指针变量的算术运算

(1)指针变量可以进行算术运算的:自增、自减、加减一个整数,但是不能乘法和除法运算。运算的结构就是指针指向前或后的地址。
(2)指针和指针之间可以做减法运算,得到的是两个地址之间有几个该和指针类型相同的元素。——注:其它指针与指针之前都运算都是违法的。

3指针与数组

3.1 指针和一维数组

定义一维数组:int x[6]={1,2,3,4,5,6};
此时一维数组的空间如下:
在这里插入图片描述
(1)在数组中,作为数组的首元素的数组名x是一个地址常量,也叫指针常量。此时的数组名x是不能被修改的。
(2)数组的最大特点之一,所占的内存空间是连续的。
运算符 [ ]其实就是指针的另一种形式,
例如:a[2]=*(a+2)=2[a]。所以给指针访问数组带来了方便。
//访问数组的形式有一下三种

int a[6], i;
for (i = 0; i < 6; i++)
{
	scanf("%d", &a[i]);
	printf("%d ", a[i]);
}

int a[6], i;
for (i = 0; i < 6; i++)
{
	scanf("%d", a+i);
	printf("%d ", *(a+i));
}

int a[6];
int *p = a;
for (; p < &a[6}; p++)
{
	scanf("%d", p);
	printf("%d ", *p);
}

(3)操作符之间的优先级问题!
*和++优先级相同,结合方向自右向左,所以指针和自增自减的时候,尽量加上();

3.2 指针和字符串

  1. a.字符串是特殊的字符数组,如:char str[]=“china\0”;里面字符是变量,可以被修改!字符串变量
    b.也可以用指针来创建字符串,如:*s=“china\0”,里面的字符是常量,不能被修改!字符串常量
  2. 对字符串的相关操作,就是要找到字符串首元素的地址还有最后的‘\0’;

3.3 指针与二维数组

  1. 指向二维数组元素的指针
    ① 二维数组就是一维数组的堆砌。
    ② 二维数组的数组名是二维数组首行的行地址。
    ③ a[i]是每行的首元素地址
  2. 指向一行数据的指针——行指针
    ①行指针声明的格式:类型(* 行指针变量名)[数组长度];
    ②行指针运用举例
#include<stdio.h>

int main()
{
	int a[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
	int sum = 0;
	int i, j;
	int(*q)[4] = a;//行指针的声明,指向二维数组a的首行
	for (i = 0; i < 3; i++)
	{
		sum = 0;
		printf("第%d行(", i + 1);
		for (j = 0; j < 4; j++)
		{
			printf("\t%d", *(*q + j));//由于q指向了二维数组a的首行数据,因此*q相当于a[0],即*a,那么*q+j就是a[0][j]的地址,所以*(*q + j)就是a[0][j]
			sum += *(*q + j);
		}
		printf(")的行和是:%d。\n", sum);
	}
	return 0;
}

4 指针数组

①指针数组在字符串中的运用:用指针数组来接受多个字符串和用二维数组来接受字符相比,指针数组所用的空间会小一点。
②指针数组声明形式:类型 * 指针数组名[数组长度];

5 指向指针的指针

一级指针为int *p=NULL;
指向一级指针的指针变量称为二级指针,也是用来存放地址;
声明形式:int **p1=&p;

6 指针与函数

6.1指针作为函数参数

函数传参有两种:①传值传参②传址传参
第一种方式相当于将实参的值拷贝给了形参
第二种方式是将地址传给形参,形参通过地址可以找主函数中的变量,从而实现了数据共享。

6.2指针作为函数返回值

返回来的地址可以访问一个或者一段数据,从而实现了函数返回多个值的功能能——一般情况下,函数只能返回一个值!

6.3指向函数的指针

(1)
①数据指针:指向整数、实数、字符、数组的指针。
函数指针:指向函数的指针。
②函数指针的相关介绍:在c语言中,函数名代表函数的入口地址。当程序在执行过程中调用某函数时,程序控制转移位置就是该函数名表示的该函数代码的入口地址。当一个指针存放该入口地址,就称该指针为指向函数的指针,简称函数指针。
③函数指针变量的声明形式:
例如程序以定义函数f:
float f(int x,int y);
则可以定义函数指针p:
float (*p)(int ,int );
并给函数指针p赋值:
p=f;

④函数指针的举例:

//指针和函数
//函数指针的主要用途是将一个函数作为另一个函数的参数

//求某个函数的定积分
#include<math.h>
//定义integral来实现求积分的值(根据同用的积分公式来定义)
double integral(double(*func)(double), int a, int b)
{
	return (b - a)*((*func)(a)+(*func)(b)) / 2;
}
//函数1
double f1(double x)
{
	return sin(x)*cos(x);
}
//函数2
double f2(double x)
{
	return x*x / 2;
}
int main()
{
	//定义一个函数指针
	double(*p)(double);
	p = f1;//求得是f1
	printf("%lf\n", integral(p, 1, 2));//输出函数integral返回来的f1积分值
	p = f2;//求得是f2
	printf("%lf\n", integral(p, 1, 2));//输出函数integral返回来的f2积分值

	return 0;
}

⑤指针函数调用函数的格式:
(*函数指针名)(实参表);
(2)函数指针和数据指针的区别
①数据指针指向内存中的数据存储区;而函数指针则是指向程序代码存储区。
②目标运算符作用于数据指针,是用来访问指针所指向的数据;而目标运算符作用于函数指针,则是将程序控制转移到指针所指向的函数入口,执行函数体。
③数据指针可以进行自增和自减等运算;函数指针则不能进行这些运算

7 结构体和指针

结构体指针概念

在这里插入图片描述

  • 37
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰深入学习计算机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值