指针操作数组
- 指针操作一维数组
//int array[3]
//数组名: 代表了这段内存首地址 --->指针
//&array[0]
//正常操作: 直接存储数组的首地址
//直接把指针当作数组名就可以了
//非正常操作:指向其他元素开始操作数组
#include <stdio.h>
int main()
{
int array[3] = { 1,2,3 };
printf("%p\n", array);
printf("%p\n", &array[0]);
int* p = array;
for (int i = 0; i < 3; i++)
{
//printf("%d\t", p[i]); //--->这种方式使用不会错误
printf("%d\t", *(p + i));
//*(p+i) 等效p[i];
}
printf("\n");
//array = array + 3; 不能修改
//array-->&array[0]
//array+3-->&array[3];
for (p = array; p < array + 3; p++)
{
printf("%d\t", *p);
//*p等效p[0] 取当前地址对应内存中值
}
printf("\n");
int test[3] = { 1,2,3 };
int* pT = &test[2];
printf("%d\n", pT[0]); //指针操作数组,用数组用法,[0]下表不一定是第0个元素
printf("%d\n", pT[-1]);
printf("%d\n", pT[1]); //未知量 -858993460
return 0;
}
//一级指针操作字符串
char str[] = "ILoveyou";
char* pstr = str + 3;
puts(pstr);
//[]操作等效取*运算
putchar(pstr[0]); //pstr[0] 等效*pstr操作,等效取当前地址下面值
//*pstr 等效*(str+3) 等效 str[3];
char* lastchar = str + 8;
putchar(lastchar[0]);
pstr = str;
printf("\n");
puts(pstr);
- 指针操作二维数组
//二维数组基础知识
//数组名:指针数组的指针
//行地址:数组名[i];
//一级指针操作二维数组 (二维数组在内存连续的)
//数组指针操作二维数组
#include <stdio.h>
//void printArray2D(int p[][3], int cols, int row)
void printArray2D(int(*p)[3], int cols, int row)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", p[i][j]); //自己写代码这样就行,怎么方便怎么来
}
printf("\n");
}
}
int main()
{
int array[2][3] = { 1,2,3,4,5,6 };
int* p = &array[0][0];
//warning C4047: “=”:“int *”与“int (*)[3]”的间接级别不同
//p = array;
printf("%p\n", array);
printf("%p\n", &array[0][0]);
printf("%p\n", array[0]);
printf("%p\n", array + 1); //12/4=3
printf("%p\n", p + 1); //4
printf("%p\n", array[0] + 1);
//char* pC = &array[0][0];
//int* pI = &array[0][0];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", *(p + j + i * 3));
//j+i*3 把坐标转为第几个元素
//p+n 等下偏移
}
printf("\n");
}
int(*pArray)[3] = NULL; //括号必须要有,列数和表示的数组的列数必须相同
//先算() ,他是一个子指针, 数组指针 指向数组的指针
//联想整形指针,指向整数
pArray = array;
//直接当作数组名去名
printf("-------------------------------\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", pArray[i][j]); //自己写代码这样就行,怎么方便怎么来
}
printf("\n");
}
printf("-------------------------------\n");
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", *(*(pArray + i) + j));
//一维数组:p[i] 等效 *(p+i)
//printf("%d\t", *(pArray[i] + j));
//取* 等效数组下表运算 *(pArray+i) (pArray+i)[0]
//printf("%d\t", *((pArray + i)[0] + j));
//printf("%d\t", ((pArray + i)[0] + j)[0]);
//printf("%d\t", (pArray[i] + j)[0]);
//看到会读就OK
}
printf("\n");
}
printf("-------------------------------\n");
printArray2D(array, 2, 3);
//存储多个字符串--->指针数组 多个指针变量
//整形数组: 多个整形变量
char* pstr[3] = { "Iloveyou","IMiss","IiIIII" }; //每一行上面字符串可以不相同,并且不浪费
//int array[3] array[0] array[1] array[2]
//pstr[0] pstr[1] pstr[2]; 分别存储的是每个字符串首地址
for (int i = 0; i < 3; i++)
{
puts(pstr[i]);
}
//字符串二维数组也可以存储多个字符串? 列数相同 会导致浪费,多余内存
return 0;
}
二级指针
//int** p=NULL;
//int*** pp=NULL;
#include <stdio.h>
int main()
{
int a = 1;
int* p = &a; //一级指针变量存储的普通变量的地址
int** pp=&p; //二级指针变量存储一级指针变量地址
//*地址 --->得到当前地址对应内存中的值
printf("%d\t%d\n", *p, p[0]);
printf("%d\t%d\n", **pp, pp[0][0]);
int array[2][3] = { 1,2,3,4,5,6 };
//一级指针算偏移
//数组指针做遍历
// warning C4047: “=”:“int **”与“int (*)[3]”的间接级别不同
// 所有这种提醒麻烦大家当作错误处理 C++当作是错误的
//pp = array;
//for (int i = 0; i < 2; i++)
//{
// for (int j = 0; j < 3; j++)
// {
// printf("%d\n", pp[i][j]);
// }
// printf("\n");
//}
return 0;
}
动态内存申请
- 动态内存申请的函数
//No.1 断言
#include <assert.h>
assert(p); //p等于 触发断点,中断程序 断言
#include <malloc.h>
//#include <stdlib.h>
//No.2 malloc 动态内存,不做初始化
void* malloc(size_t _Size); //size:申请内存的总字节数
//No.3 calloc 动态内存申请,会初始化为0
void* calloc( size_t _Count,size_t _Size); //有几个数据:count,每个数据占用的字节数:size
//No.4 realloc 内存重新申请,保留原数据
void* realloc(void* _Block,size_t _Size); //原指针,重新申请的内存大小
//No.5 释放内存函数
void free(void* _Block);
//__cdecl 调用准则,限定参数传参顺序(入栈顺序)--->了解一下
//_In_ 参数类型修饰 传入
//_out_ 传出参数
//size_t unsigned int
//void* 使用前必须强制类型转换
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
int main()
{
//No.1 malloc使用方式
int* p = NULL;
//assert(p); //p等于 触发断点,中断程序 断言
//1.一级指针动态申请内存成为一维数组
p = (int*)malloc(sizeof(int) * 3); // int p[3];
assert(p);
//等效:
//if (p == NULL)
// return 0;
//(指针类型)malloc(sizeof(指针所指向的类型)*个数);
//int* p
//指针的类型: 去掉变量名: int*
//指针所指向类型: 去掉变量名和* :int (操作的数据类型)
for (int i = 0; i < 3; i++)
{
p[i] = i;
printf("%d\t", p[i]);
}
printf("\n");
//数组经典错误
int num = 0;
scanf_s("%d", &num);
//int array[num]; //错误 ,定义数组长度必须是常量
//C语言可以不写,建议写上,证明你学过void*
int* pMeory = (int*)malloc(sizeof(int) * num); //理解为一个数组
assert(pMeory);
//什么时候释放,当你不需要他的时候释放
//注意点: 从那里申请的一定要从那里释放
pMeory++;
//.....
//无效堆栈指针
pMeory--;
free(pMeory);
pMeory = NULL; //防止野指针
free(p);
p = NULL; //防止野指针
//直到整个程序关掉,内存才会操作系统回收
//No.2 calloc使用方式
int* pc = (int*)calloc(3, sizeof(int)); //3也可以变量
assert(pc);
for (int i = 0; i < 3; i++)
{
printf("%d\t", pc[i]);
}
printf("\n");
int* pr = realloc(pc, sizeof(int) * 6); //sizeof(int) * 6一定要比原来大小要大
assert(pr);
for (int i = 0; i < 6; i++)
{
printf("%d\n", pr[i]);
}
//free(pc);
//pc = NULL;
free(pr);
//free(pr); 同一段内存不能被重复释放
pr = NULL;
//指针充当变量只有两种途径
//1.指向变量
int a = 1;
int* pa = &a;
*pa = 1234;
int result = (*pa) * 3;
//2.动态内存申请
//申请一个变量内存
int* pM = NULL;
pM = (int*)malloc(sizeof(int));
assert(pM);
*pM = 1003;
free(pM);
//二维数组的申请
//二级指针
//二级指针申请
int** pArray = NULL;
pArray = (int**)malloc(sizeof(int*) * 4); //p[0] p[1] p[2] p[3]
assert(pArray);
for (int i = 0; i < 4; i++)
{
pArray[i] = (int*)malloc(sizeof(int) * 3);
assert(pArray[i]);
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
pArray[i][j] = i * j;
printf("%d\t", pArray[i][j]);
}
printf("\n");
}
//释放顺序和申请顺序相反的
for (int i = 0; i < 3; i++)
{
free(pArray[i]);
}
free(pArray);
//数组指针申请维数组
int(*p2D)[4] = NULL;
//(指针类型)malloc(sizeof(指针所指向的类型)*个数);
p2D = (int(*)[4])malloc(sizeof(int[4]) * 3);
assert(p2D);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
p2D[i][j] = i * j;
printf("%d\t", p2D[i][j]);
}
printf("\n");
}
free(p2D);
p2D = NULL;
return 0;
}