C语言 指针的应用

目录

一:指针偏移

二:指针应用

三:有关指针的小练习

四:指针 & 数组

五:指针变量操作一维数组

六:指针变量操作字符数组

七:字符数组 & 字符指针 作为函数返回值

八:存储类别


一:指针偏移

指针是地址,可以偏移

指针偏移量是根据基础数据类型来决定的,示例如下:

示例一:int数据类型偏移量是4 

#include<stdio.h>

int main()
{	
   int a=3;
   int *p=NULL;//定义1 定义并赋初值
    p=&a;
	printf("a的地址:%p\n",p);//a的地址:0019FF2C
	p++;
	printf("a的地址:%p\n",p);//a的地址:0019FF30
	return 0;
}

示例二:char数据类型偏移量是1 

#include<stdio.h>

int main()
{	
	char name[6]="admin";
	char* pt = name;
	printf("name的地址是:%p\n",pt);//name的地址是:0019FF28
	pt++;
	printf("name的地址是:%p\n",pt);//name的地址是:0019FF29
}

如上对比分析,不难看出,指针的偏移量是根据基础数据类型决定的

二:指针应用

例如可将  控件添加函数  迭代更新,具体如下

当 ctrlCount控件数量 用int数据类型修饰传参的时候 需要 return返回 int 函数类型

int addControl(CONTROL_T ctrl,CONTROL_T ctrlArr[20] , int ctrlCount)
{
	ctrlArr[ctrlCount++]=ctrl;//通过下标将控件ctrl放到控件数组ctrlArr[20]当中 
	//	ctrlCount记录控件总个数 添加控件其下标数
	return ctrlCount;
}

而现在学习了指针,可以使用 int *数据类型修饰 ctrlCount ,使用 *取地址中的值,无需return返回 直接使用void 函数类型 即可

void addControl(CONTROL_T ctrl,CONTROL_T ctrlArr[20] , int *ctrlCount)
{
	ctrlArr[(*ctrlCount)++]=ctrl;//通过下标将控件ctrl放到控件数组ctrlArr[20]当中 
	//	ctrlCount记录控件总个数 添加控件其下标数
}

也就是按值传递变成按地址传递,函数内部改变,外部也可以变

若是按值传递则需要返回,如int类型数据 return返回,外部才可以获取信息

但是采用按地址传递,就不用返回,函数类型可以直接设置为void

对指针数据类型 如上 int*函数参数 在传参(函数调用的时候) 需要 &取地址 传递函数参数 ,如下示例

添加控件函数的调用:addControl(title,loginWin.ctrlArr,&loginWin.ctrlCount);//通过地址获取信息

三:有关指针的小练习

1.定义一个int类型的变量 ,定义一个int类型指针 接受变量的地址

2.定义一个char类型的字符数组[10] ,定义一个char类型指针 接受变量的地址,( 获取下标为5的元素)

结果如下: 

#include<stdio.h>
int main()
{
	int a=1;
	char name[10]="abcdefgh";
	int *p=NULL;//定义并赋初值
	char*pt=NULL;//定义并赋初值
	p=&a;//int 取a的值
	pt=name;//char 取name数组内容
	printf("打印int a的地址%p\n",p);//整型a地址 打印int a的地址0019FF2C
    printf("打印int a的值%d\n",*p); //整型a值 打印int a的值1
	printf("打印char name下标5元素地址%p\n",pt);//打印char name下标5元素地址0019FF20
	printf("打印char name下标5元素的值%c\n",*(pt+5));//下标为5值 打印char name下标5元素的值f
	return 0;
}

四:指针 & 数组

1.数组的指针就是数组的起始地址就是数组名

数组的指针是常量指针【不可以改变】,示例如下

#include<stdio.h>

void test1()
{
	int numArr[5]={0,1,2,3,4};
	int *p=numArr;
	printf("%p\n",p);     //0019FEC8
	printf("%p\n",numArr);//0019FEC8
	printf("%p\n",p+2);   //0019FED0  指针偏移
    printf("%p\n",numArr+2); //0019FED0  指针偏移
}

int main()
{
	test1();
	return 0;
}

2.指针偏移【两种写法】

写法一: 先指针变量存储数组地址,后再指针变量偏移,示例如下

#include<stdio.h>

void test1()
{
	int numArr[5]={0,1,2,3,4};
	int *p=numArr;
	p+=2;
	printf("%d  %p\n",*p,p);//2  0019FED0
}

int main()
{
	test1();
	return 0;
}

写法二: 在指针变量存储数组地址的同时,直接指针变量偏移

#include<stdio.h>

void test1()
{
	int numArr[5]={0,1,2,3,4};
	int *p = numArr+2;
	printf("%d  %p\n",*p,p);//2  0019FED0
}

int main()
{
	test1();
	return 0;
}

五:指针变量操作一维数组

指针访问数组【两种方式】

1. 指针[下标]方式

2. 指针偏移量方式

指针[下标]方式  &  指针偏移量方式 操作一维数组,示例如下

#include<stdio.h>

void test1()//指针变量操作一维数组
{
	int numArr[5]={0,1,2,3,4};
	int *p=numArr;
	//数组名是起始地址 第一个元素的地址
	printf("%d   %p\n",*p,p);//0   0019FEC8

    printf("%d\n",numArr[1]);//1  指针下标
	printf("%d\n",p[2]);     //2  指针下标
	printf("%p\n",p+2);      //0019FED0  指针偏移
}

int main()
{
	test1();
	return 0;
}

保存第二个元素的地址 示例:

#include<stdio.h>

void test1()//指针变量操作一维数组
{
	int numArr[5]={0,1,2,3,4};
	int *p=numArr;
	//保存第二个元素的地址
	p=&numArr[1];
	printf("%d\n",*p);//1
	printf("%p\n",p); //0019FECC
}

int main()
{
	test1();
	return 0;
}

查看第四个元素的值 示例:

#include<stdio.h>

void test1()//指针变量操作一维数组
{
	int numArr[5]={0,1,2,3,4};
	int *p=numArr;
	printf("%d\n",*(numArr+3));//3   *取值
}

int main()
{
	test1();
	return 0;
}

注意点:写法numArr++不可以(是错误的写法),因为 指针变量才可以++,而数组地址(常量)系统开辟空间是固定的,不可以++【数组的指针是常量指针,不可以++

数组的访问方式:

数组名[下标]     

*(数组名+偏移量)

数组作为参数(三种表示)

char str[10]

char str[ ]

char *str

数组作为返回值,函数类型如char* demo1(){代码}  return "admin";

(char类型返回,则函数类型为char*)

当然也有如int* demo2(){代码},函数类型是int *

六:指针变量操作字符数组

数组的访问方式:

数组名[下标]     

*(数组名+偏移量)

#include<stdio.h>

void test2()//指针变量操作字符数组
{
	char name[6]="admin";
	char *pt=name;
	printf("%s\n",name);//admin
	printf("%s\n",pt);  //admin
	printf("%c\n",name[1]);  // d
	printf("%c\n",*(pt+1));  // d   *(指针变量+偏移量)
}

int main()
{
	test2();
	return 0;
}

字符数组元素可以修改  示例如下

#include<stdio.h>

void test2()//指针变量操作字符数组
{
	char name[6]="admin";
	char *pt=name;

	name[1]='s';   //字符数组元素修改
	printf("%s\n",name); //asmin
	printf("%s\n",pt);   //asmin
	printf("%c\n",name[1]);  // s
	printf("%c\n",*(pt+1));  // s    *(指针变量+偏移量)
}

int main()
{
	test2();
	return 0;
}

字符常量指针元素不可以修改,示例如下,会出现程序异常现象

#include<stdio.h>

void test2()
{
	char *ps="hello";  //字符串常量 存储在常量区
    ps[1]='a';         //常量不可修改 程序运行会出现异常
	printf("%s\n",ps);//程序异常,没有任何打印
	printf("%c\n",*(ps+1));  
}

int main()
{
	test2();
	return 0;
}

七:字符数组 & 字符指针 作为函数返回值

#include<stdio.h>

char *test1()    //(字符数组作为返回值)
{
	char name[6]="lily";  //局部变量系统回收
	return name;
}

char *test2()    //(字符指针作为返回值)
{
	char *str="hello";   //字符常量指针  常量区 可以正常打印hello
	return str;
}

int main()
{	
	char *ps=NULL,*pt=NULL;
	ps=test1();
	pt=test2();
	printf("%s\n",ps);//0.
	printf("%s\n",pt);//hello
	return 0;
}

可以看出字符数组作为返回值,打印出信息非理想信息,也就是说在字符数组作为返回值的时候,系统回收

字符指针作为返回值,常量区不会被回收,因此可以打印出hello完整信息

对于字符数组作为返回值解决如下:

字符数组作为参数传入,示例如下

#include<stdio.h>

void test3(char *name)//字符数组作为参数传入
{
	name[0]='s';   

}    //内部传参进行修改,外部即可以获取

int main()
{	
	char str[10]={0};
    test3(str);
    printf("%s\n",str);//s
	return 0;
}

八:存储类别

内存中的存储区域包括有:

程序代码区:存放函数体的二进制代码

静态区/全局区(static):全局变量和静态变量的存储区域

区(heap):程序员分配释放

区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chenruhan_QAQ_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值