C语言 指针的高级使用

目录

一:数组 & 指针  恒等价关系式

二:指针访问二维数组

三:行指针

四:指针数组 & 数组指针

五:指针数组 & 行指针

六:指针数组 & 二维字符数组

七:指针数组的访问

八:结构体指针


一:数组 & 指针  恒等价关系式

num[1] == *(num+1) 恒等价,证明示例如下

#include<stdio.h>

int main()
{
	int num[10]={0,1,2,3,4,5};
	int *p=num;
	printf("%d\n",num[1]);//1  
	printf("%d\n",*(p+1));//1
	printf("%d\n",*(num+1));//1
}

二:指针访问二维数组

基于  num[1] == *(num+1) 恒等价

指针访问二维数组 5种方式,具体示例如下分别给出

1.数组名[行索引][列索引] 示例如下

#include<stdio.h>

int main()
{
    int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i=0,j=0;
	for(i=0;i<3;i++)  //遍历行索引
	{
		for(j=0;j<4;j++)  //遍历列索引
		{
			printf("%d\t",nums[i][j]);//数组名[行索引][列索引]
		}
		printf("\n");
	}
}

2.*(数组名[行索引]+偏移量) 示例如下

#include<stdio.h>

int main()
{
    int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i=0,j=0;
	for(i=0;i<3;i++)  //遍历行索引
	{
		for(j=0;j<4;j++)  //遍历列索引
		{
            //nums[i]   一维数组的首地址  每一行的数组名
            printf("%d\t",*(nums[i]+j)); //*(数组名[行索引]+偏移量)
		}
		printf("\n");
	}
}

3.基于2又num[1] == *(num+1)  恒等价 示例如下

#include<stdio.h>

int main()
{
    int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i=0,j=0;
	for(i=0;i<3;i++)  //遍历行索引
	{
		for(j=0;j<4;j++)  //遍历列索引
		{
			printf("%d\t",*(*(nums+i)+j));//num[1] == *(num+1)恒等价
		}
		printf("\n");
	}
}

4.基于3又[j]不变 示例如下

#include<stdio.h>

int main()
{
    int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i=0,j=0;
	for(i=0;i<3;i++)  //遍历行索引
	{
		for(j=0;j<4;j++)  //遍历列索引
		{
			printf("%d\t",(*(nums+i))[j]);//[j]不变
		}
		printf("\n");
	}
}

5.第i行第j列元素 示例如下

#include<stdio.h>

int main()
{
    int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i=0,j=0;
	for(i=0;i<3;i++)  //遍历行索引
	{
		for(j=0;j<4;j++)  //遍历列索引
		{
           	printf("%d\t",*(&nums[0][0]+i*4+j));//第i行第j列元素
		}
		printf("\n");
	}
}

可以单独打印7【以第 i 行 第 j 列 的方式】,示例如下

#include<stdio.h>

int main()
{
    int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
    printf("%d\n",*(&nums[0][0]+1*4+2));  //得到7 第二行 第三列元素
}

三:行指针

行指针写法如:*(nums+i)   

在 二维数组的访问 行列偏移最好用

行指针 示例如下:

#include<stdio.h>

void test1()
{
	//*(nums+i)  行指针  二维数组的访问行列偏移最好用	
	int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	printf("%d\n",*(*(nums+1)+2));//7     第二行 第三列元素    
}

int main()
{
	test1();
}

行指针访问二维数组 示例

#include<stdio.h>

int nums[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
//arr[][列]   arr[]  (*arr)[4]函数封装    (*arr)[4]就是行指针+偏移量
// 二维数组中列不能少,一定要写列数
//行指针几个字节:占用系统空间是4个字节(指针都是占用4字节)
void printSecond(int (*arr)[4],int row)
{
	int i=0,j=0;
	for(i=0;i<row;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("%d\t",(*(arr+i))[j]);		
		}
		printf("\n");	
	}
}

int main()
{
   printSecond(nums,3);      
}

四:指针数组 & 数组指针

数组指针:本质是指针,就是数组名 也就是 数组的起始地址 也就是 存储数组的地址

指针数组:本质是数组,元素是指针 的 数组;  指针【保存地址】

指针数组  示例如:int *pt [5]  就是表示长度是5的int类型的指针组成的数组

对于char* :存储字符数组的首地址;指针数组,具有内存优势

使用 指针数组写法 存储字符串数组 【内存优势】 

char *pstr[4]={“lily”,”rose”,”admin”,”hellokity”}; //长度为4的指针数组 存储字符串数组

小结:

指针数组的作用:保存多个字符串

指针数组的优点:具有内存优势【 4*4=16个字节(char *4是字节 长度为4的指针数组)】

五:指针数组 & 行指针

要注意区分好   指针数组  &    行指针+偏移量  【写法很像 容易混淆 需要注意!!!】

*pstr[4]指针数组

(*pstr)[4]:行指针+偏移量【行指针进行偏移访问二维数组】

六:指针数组 & 二维字符数组

二维字符数组写法如下: 

char names[4][10]={"lily","rose","admin","hellokity"};

指针数组写法如下:

char *pstr[4]={"lily","rose","admin","hellokity"};

二维字符数组 & 指针数组 的区别如下:

1. 存储区域:

    二维字符数组:存储区域  栈区 

    指针数组:       字符串常量  值存储在常量区   地址存储在栈区

2. 内存占用:

     二维字符数组:4*10=40 

     指针数组4*4=16内存占用方面,指针数组更有优势

3. 元素类型: 

      二维字符数组:存储的元素是字符  

      指针数组:存储的元素是指针【地址】

七:指针数组的访问

指针数组的元素的访问,示例如下

两种写法:下标法  &  指针偏移量

#include<stdio.h>

int main()
{
	char *pstr[4]={"lily","rose","admin","hellokity"}; //指针数组
	//获取首地址就可以打印字符串
	printf("%s\n",pstr[1]);    //rose
	printf("%s\n",pstr[0]);    //lily 
	printf("%s\n",*(pstr+2));  //admin
}

八:结构体指针

结构体指针【按值传递 ---》按地址传递】

结构体指针 存储单个结构体 示例如下

#include<stdio.h>
#define ADMIN 1
#define MANAGER 2
#define WAITER 3

//用户结构体声明
typedef struct user_t
{
	int ID;
	char name[20];
	char pwd[20];
	int role;    //数字表示角色 1是admin  2是 manager 3 是waiter
}USER_T;

void demoStructPoint()
{
	//结构体指针  指针都是占用4字节  
	USER_T user={1004,"haha","123456",2};
	//数据类型*变量名
	USER_T *userPoint = NULL;//指针变量初始化
	userPoint = &user;//指针变量--存储别人的地址
	printf("%d\n",user.ID);        //1004 结构体访问属性(成员变量)用.运算符
	printf("%d\n",(*userPoint).ID);//1004
    printf("%d\n",userPoint->ID);  //1004 结构体指针访问属性(成员变量)用->运算符
}

int main()
{
  demoStructPoint();
}

用户修改后的密码为:123123   具体实现如下:

函数参数是结构体指针数据类型 无需return 直接设置void函数类型调用时 需要&符号

[如下面的写法是:

 先 对指针变量初始化;

 后 存储别人的地址;

 最后直接调用 指针变量 userPoint]

#include<stdio.h>
#include<string.h>
#define ADMIN 1
#define MANAGER 2
#define WAITER 3

//用户结构体声明
typedef struct user_t
{
	int ID;
	char name[20];
	char pwd[20];
	int role;    //数字表示角色 1是admin  2是 manager 3 是waiter
}USER_T;

void modifyUser(USER_T *newUser)
{
	strcpy(newUser->pwd,"123123");
}

void demoStructPoint()
{
	//结构体指针  指针都是占用4字节  
	USER_T user={1004,"haha","123456",2};
	//数据类型*变量名
	USER_T *userPoint = NULL;//指针变量初始化
	userPoint = &user;//指针变量--存储别人的地址
    modifyUser(userPoint);
	printf("用户修改后的密码为:%s\n",userPoint->pwd);
}

int main()
{
   USER_T newuser={0};//定义新用户
   demoStructPoint();
}

结构体数组【数组名即地址 无需&符号】

[如下面的写法是:

先 对指针变量初始化;

后 存储别人的地址 userArrs;【数组名即地址 无需&符号

最后直接调用 指针变量 userPoint]

#include<stdio.h>
#define ADMIN 1
#define MANAGER 2
#define WAITER 3

//用户结构体声明
typedef struct user_t
{
	int ID;
	char name[20];
	char pwd[20];
	int role;    //数字表示角色 1是admin  2是 manager 3 是waiter
}USER_T;

int main()
{
  	USER_T user={1004,"haha","123456",2};//结构体
    USER_T userArrs[10]={                //结构体数组
		{1001,"admin","123456",ADMIN},
		{1002,"waiter","123456",WAITER}
	};
	//数据类型*变量名
	USER_T *userPoint=NULL;
	userPoint=userArrs;//数组名即地址,指针变量存储别人的地址
	printf("%s\n",userArrs[1].name);   //waiter  结构体用.运算符
	printf("%s\n",userPoint->name);    //admin   结构体指针用->运算符
	printf("%s\n",(userPoint+1)->name);//waiter (地址偏移-结构体指针)使用->运算符
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chenruhan_QAQ_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值