目录
一:数组 & 指针 恒等价关系式
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 (地址偏移-结构体指针)使用->运算符
}