c语言基础笔记(10.c语言指针)

10 c语言指针

10.1 指针

10.1.1 指针的概念
指针变量也是一个变量;
指针存放的内容是一个地址,该地址指向一块内存空间
10.1.2 指针变量的定义
可以定义一个指向一个变量的指针变量
Int *p; //表示定义一个指针变量
*p; //代表指针所指内存的实际数据
切记,指针变量只能存放地址,不能将一个int型变量直接赋值给一个指针。
Int *p = 100;
Int *p = &a; //得到变量a的地址,将这个地址赋值给变量p
Int *p1;//定义一个变量,名字叫p1,它可以指向一个int的地址
P1=&b;//指针变量的值一般不能直接赋值一个整数,而是通过取变量地址的方式赋值
10.1.3 &取地址运算符
&可以取得一个变量在内存当中的地址
10.1.4 无类型指针
定义一个指针变量,但不指定它指向具体哪种数据类型。可以通过强制转化将void *转化为其他类型指针,也可以用(void *)将其他类型指针强制转化为void类型指针。
Void *p;
10.1.5 NULL
NULL在C语言中的定义为(void *)0;
当一个指针不指向任何一个有效内存地址的时候,我们应该把指针设置为NULL。
10.1.6 空指针与野指针
指向NULL的指针叫空指针,没有具体指向任何变量地址的指针叫野指针。
空指针是合法的,但野指针是危险的,是导致程序崩溃的主要原因。
10.1.7 指针的兼容性
指针之间赋值比普通数据类型赋值检查更为严格,例如:不可以把一个double *赋值给int *;
原则上一定是相同类型的指针指向相同类型的变量地址,不能用一种类型的指针指向另一种类型的变量地址。
10.1.8 指向常量的指针与指针常量
Const char * p; //定义一个指向常量的指针
Char *const p;//定义一个指针常量,一旦初始化之后其内容不可改变。
10.1.9 指针与数组的关系
一个变量有地址,一个数组包含若干个元素,每个元素在内存中都有地址。
Int a[10];
Int *p = a;
比较p和&a[0]的地址是否相同。
10.1.10 指针运算
指针运算不是简单的整数加减法,而是指针指向的数据类型在内存中占用字节数作为倍数的运算。
Char *p;
P++; //移动了sizeof(char)这么多的字节数
int *p1;
P1++; //移动了sizeof(int)这么多的字节数
赋值:int *p = &a;
求值:int i = *p;
取指针地址int **pp = &p;
将一个整数加(减)给指针:p+3;p-3;
增加(减少)指针值 p++,p–
求差值,p1-p2,通常用于同一个数组内求两个元素之间的距离。
比较p1= =p2,通常用来 比较两个指针是否指向同一个位置。

10.1.11 通过指针使用数组元素
P+1代表&a[1],也可以直接使用p[1]表示a[5]
P +5代表&a[5];
P++
寻找数组第二大元素
第一步:假设数组中前2个元素就是最大的和第二大的
Max
Smax
第二步:从数组的第2号元素开始遍历数组
当有元素大于max的时候,
Smax = max
Max= 最大的那个元素,
如果当前元素小于max,并且大于smax,那么就让smax等于当前那个元素
int smax(int *s)//求数组中第二大元素

{
	int max = 0;
	int s_max = 0;
	int i;
	if (*s > *(s +1))
	{
		max = *s;
		s_max = *(s + 1);
	}
	else
	{
		max = *(s + 1);
		s_max = *s;
	}//将max等于s[0]和s[1]中大的那个元素的值
	for(i = 2;i < 10;i++)//从第3个元素开始遍历数组
	{
		if(max < *(s + i))//如果遇到大于max的元素,那么让s_max等于max,让max等于这个元素
		{
			s_max = max;
			max = *(s + i);
		}
		else if(max > *(s + i) && *(s + i) > s_max)//如果这个元素是介于max和s_max之间,那么就让这个元素等于s_max
		{
			s_max = *(s + i);
		}
	}
	return s_max;//返回s_max的值
}
int main()
{
	int buf[10] = {34,21,56,4,87,90,15,65,72,48};
	
	printf("%d\n",smax(buf));
	return 0;
}
    
#include<string.h>
//通过指针将字符串逆置
int main()
{
	char str[100]="you";
	char *str_start = &str[0];
	char *str_end = &str[strlen(str) - 1];
	while(str_start < str_end)
	{
		char *tmp = * str_start;
		* str_start = * str_end;
		* str_end = tmp;
		str_start ++;
		str_end --;
	}
	printf("%s\n",str);
	return 0;
}
对于VS的汉字是GBK编码,一个汉字2个字节;对于QT汉字是UTF8编码,一个汉字是3个字节。
#include<string.h>
//通过指针将汉字字符串逆置
int main()
{
	char str[100]="我爱你";
	short *str_start = &str[0];
	short *str_end = &str[strlen(str) - 2];
	while(str_start < str_end)
	{
		short *tmp = * str_start;
		* str_start = * str_end;
		* str_end = tmp;
		str_start ++;
		str_end --;
	}
	printf("%s\n",str);
	return 0;
}

10.1.12 指针数组
int *a[10];//定义了一个指针数组,一共10个成员,其中每个成员都是int *类型
10.1.13 指向指针的指针(二级指针)
指针就是一个变量,既然是变量就也存在内存地址,所以可以定义一个指向指针的指针。
通过二级指针修改内存的值;
Int I = 10;
Int *p1 = &I;
Int **p2 = &p1;
Printf(“%d\n”,**p2);
|

以此类推可以定义3级甚至多级指针。
C语言允许定义多级指针,但是指针级数过多会增加代码的复杂性,考试的时候可能会考多级指针,但是实际编程的时候最多用到3级指针,但是3级指针也不常用,一级和二级指针是大量使用的。
10.1.14 指向二维数组的指针

{
	int buf[3][5] = {{2,4,3,5,1},{7,2,6,8,1},{7,3,9,0,2}};
	int i;
	int j;
	int sum;
	for(i = 0;i < 3;i ++)
	{
		sum = 0;
		for(j = 0;j < 5;j ++)
		{
			sum += (*(*(buf + i) + j));
			//sum += buf[i][j];
		}
		printf("%d\n",sum / 5);
	}
	for(i = 0;i < 5;i ++)
	{
		sum = 0;
		for(j = 0;j < 3;j ++)
		{
			sum += (*(*(buf + j) + i));
			//sum += buf[j][i];
		}
		printf("%d\n",sum / 3);
	}
	return 0;
}

10.1.15 指针变量作为函数的参数
函数的参数可以是指针类型 *,它的作用是将一个变量的地址传送给另一个函数。
通过函数的指针参数可以间接的实现形参修改实参的值。
10.1.16 一维数组名作为函数参数
当数组名作为函数参数时,C语言将数组名解释为指针
int func(int array[10]);//数组名代表数组的首地址
10.1.17 二维数组名作为函数参数
二维数组做函数参数时可以不指定第一个下标。
int func(int array[][10]);
将二维数组作为函数的参数用例不是特别多见。
10.1.18 const关键字保护数组内容
如果讲一个数组作为函数的形参传递,那么数组内容可以在被调用函数内部修改,有时候不希望这样的事情发生,所以要对形参采用const参数。
func(const int array[]);
10.1.19 指针作为函数的返回值
return NULL;
10.1.20 指向函数的指针
指针可以指向变量、数组,也可以指向一个函数。
一个函数在编译的时候会分配一个入口地址,这个入口地址就是函数的指针,函数名称就代表函数的入口地址。
函数指针的定义方式:int (*p)(int);//定义了一个指向int func(int n)类型函数地址的指针。
1 定义函数指针变量的形式为:函数返回类型(指针变量名称)(参数列表)
2 函数可以通过函数指针调用
3 int(
p)()代表指向一个函数,但不是固定哪一个函数
Void *p(int ,char *);//声明了一个函数,函数的名字叫p,函数的返回值是void *,函数的参数是int和char *
Void (*p)(int ,char *);//定义了一个指向参数为int和char *,返回值为void的函数指针
Int *(*p)(int *);//定义一个参数为int *,返回值为int *的指向函数的指针
Int *p(int *);//声明了一个函数,返回值是int *,参数是int *
Int (*p)(int , int );//定义了一个指向函数的指针,可以指向两个参数,都是int,返回值也是int类型
在回调函数和运行期动态绑定的时候大量的用到了指向函数的指针。
10.1.21 把指向函数的指针作为函数的参数
将函数指针作为另一个函数的参数称为回调函数。

int max(int a,int b)
{
	if(a > b)
		return a;
	else
		return b;
}
int add(int a,int b)
{
	return a + b;
}
int func(int (*p)(int,int),int a,int b)//第一个参数是指向函数的指针
{
	return p(a,b);//通过指向函数的指针调用一个函数
}
int main()
{
	int i = func(add,6,9);//add函数在这里就叫回调函数
	printf("i = %d\n",i);
	return 0;
}

10.1.22 memset,memcpy,memmove函数
这三个函数分别实现内存设置,内存拷贝,内存移动。
使用memcpy的时候,一定要确保内存没有重叠区域。
#include <sting.h>
memset(buf, 0, sizeof(buf));//第一个参数是要设置的内存地址,第二个参数是要设置的值,第三个参数是内存大小,单位:字节。
memcpy(buf2, buf1, sizeof(buf1));//将buf1的内存内容全部拷贝到buf2,拷贝大小为第三个参数:字节。
memmove(buf2, buf1, sizeof(buf1));//并没有改变原始内存的值。
10.1.23 指针小结
在这里插入图片描述

写在最后:最近和朋友一起在微信公众号做一些自己热爱的东西,并有许多的干货分享,大家多多关注啊!!
公众号 [越陌的数字生活]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值