数据结构学习(二)指针和内存那些事儿
地球人都知道,C语言中内存和指针一直是很多人不甚明白的地方,两者的关系也一直是犹抱琵琶半遮面,让人迷惑不解。
最近编写了个初始化三元组Triplet的函数,通过调试分析,指针和内存那层神秘的面纱被层层揭破,其实,也就那么回事儿。
初始化三元组函数如下,内有详细的注释,很容易看懂,这个不是我们的重点,我们重点是分析内存和指针两者的关系。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 引用查找路径 两种引用方式 */
#include<stdio.h>
#include<stdlib.h>
/* 定义常量 增强可读性*/
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OVERFLOW 3
/* 定义类型别名 增强可读性 */
typedef int Status;
typedef int Boolean;
/* 分配一个整形三元组的内存空间,返回该片内存空间首地址 */
int *InitTriplet(int v1,int v2,int v3)
{
int *T = (int *)malloc(3*sizeof(int));
if(!T)
exit(OVERFLOW);
T[0] = v1;
T[1] = v2;
T[2] = v3;
return T;
}
/* 程序入口 */
int main(char *argc , char **argv)
{
/* 定义并声明T,获得内存首址 */
int *T = InitTriplet(1,2,3);
/* 如果T,则说明内存分配成功 */
if(T)
{
printf("内存分配成功!\n");
printf("\nT表示的地址为%x,*T的值,也就是T[0]的值为:%d",T,(int)T[0]);
printf("\nT+1表示的地址为%x,*(T+1)的值,也就是T[1]的值为:%d",T+1,(int)T[1]);
printf("\nT+2表示的地址为%x,*(T+2)的值,也就是T[2]的值为:%d\n",T+2,(int)*(T+2));
}
/* 如果!T,则说明内存分配失败 */
else
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
//暂停以便输出
system("pause");
//无论如何,返回
return OK;
}
#include<stdio.h>
#include<stdlib.h>
/* 定义常量 增强可读性*/
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OVERFLOW 3
/* 定义类型别名 增强可读性 */
typedef int Status;
typedef int Boolean;
/* 分配一个整形三元组的内存空间,返回该片内存空间首地址 */
int *InitTriplet(int v1,int v2,int v3)
{
int *T = (int *)malloc(3*sizeof(int));
if(!T)
exit(OVERFLOW);
T[0] = v1;
T[1] = v2;
T[2] = v3;
return T;
}
/* 程序入口 */
int main(char *argc , char **argv)
{
/* 定义并声明T,获得内存首址 */
int *T = InitTriplet(1,2,3);
/* 如果T,则说明内存分配成功 */
if(T)
{
printf("内存分配成功!\n");
printf("\nT表示的地址为%x,*T的值,也就是T[0]的值为:%d",T,(int)T[0]);
printf("\nT+1表示的地址为%x,*(T+1)的值,也就是T[1]的值为:%d",T+1,(int)T[1]);
printf("\nT+2表示的地址为%x,*(T+2)的值,也就是T[2]的值为:%d\n",T+2,(int)*(T+2));
}
/* 如果!T,则说明内存分配失败 */
else
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
//暂停以便输出
system("pause");
//无论如何,返回
return OK;
}
下面的两张图片才是亮点,应该比较明白的说清楚了指针和内存的那些事儿,虽然他们的事儿还挺多的。
下面的图片是运行结果:
其实指针并不神秘,内存管理也就那样,但是要用好两者还是要心细如发,不能大意。
下面的代码是三元组数据结构的代码,实现了新建,排序,设置值,获取值,最大值等功能,这里需要理解引用变量和赋值变量的区别!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 引用查找路径 两种引用方式 */
#include<stdio.h>
#include<stdlib.h>
/* 定义常量 增强可读性 */
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OVERFLOW 3
/* 顺序存储结构 Triplet为int *类型 */
typedef int *Triplet;
/* 定义类型别名 增强可读性 */
typedef int Status;
typedef int Boolean;
/* 分配一个整形三元组的内存空间,返回该片内存空间首地址 */
int *InitTriplet(int v1,int v2,int v3)
{
int *T = (int *)malloc(3*sizeof(int));
if(!T)
exit(OVERFLOW);
T[0] = v1;
T[1] = v2;
T[2] = v3;
return T;
}
/* 采用引用参数 T是int *类型的Triplet的引用,改变T,也就是改变Triplet*/
Status InitTriplet2(Triplet &T,int v1,int v2,int v3)
{
T = (int *)malloc(3*sizeof(int));
if(!(T))
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
else
{
(T)[0] = v1;
(T)[1] = v2;
(T)[2] = v3;
}
return OK;
}
/* 销毁三元组 T为Triplet的别名(引用) */
Status DestroyTriplet(Triplet &T)
{
//如果T不为NULL,才释放
if(T)
{
free(T);
}
//设置T为0x00000000,也就是NULL
T = NULL;
return OK;
}
/* 用e返回T的第i个值 */
Status Get(Triplet T,int i,int &e)
{
if(i<1 || i>3) return ERROR;
e = T[i-1];
return OK;
}
/* 设置T的第i个值 */
Status Set(Triplet &T,int i,int e)
{
if(i<1 || i>3) return ERROR;
T[i-1] = e;
return OK;
}
/* 判断三元组是否升序排列 */
Boolean IsAscending(Triplet T)
{
return (T[0] <= T[1]) && (T[1] <= T[2]);
}
/* 判断三元组是否升序排列 */
Boolean IsDescending(Triplet T)
{
return (T[0] >= T[1]) && (T[1] >= T[2]);
}
/* 最大值用e返回 */
Status Max(Triplet T,int &e)
{
e = (T[0] >= T[1]) ? (T[0] >= T[2]?T[0]:T[2]):(T[1] >= T[2]?T[1]:T[2]);
return OK;
}
/* 最大值用e返回 */
Status Min(Triplet T,int &e)
{
e = (T[0] <= T[1]) ? (T[0] <= T[2]?T[0]:T[2]):(T[1] <= T[2]?T[1]:T[2]);
return OK;
}
/* 程序入口 */
int main(char *argc , char **argv)
{
int *T2 = NULL;
if(InitTriplet2(T2,4,5,6))
{
printf("1.内存分配成功!\n");
printf("\nT2表示的地址为%x,*T2的值,也就是T2[0]的值为:%d",T2,(int)T2[0]);
printf("\nT2+1表示的地址为%x,*(T2+1)的值,也就是T2[1]的值为:%d",T2+1,(int)T2[1]);
printf("\nT2+2表示的地址为%x,*(T2+2)的值,也就是T2[2]的值为:%d\n",T2+2,(int)*(T2+2));
int tmp;
Get(T2,2,tmp);
printf("T2[1]的值为:%d\n",tmp);
if(IsAscending(T2))
{
printf("T2升序排列\n");
}
else if(IsDescending(T2))
{
printf("T2降序排列\n");
}
else
{
printf("T2完全无序\n");
}
Set(T2,2,8);
Get(T2,2,tmp);
printf("T2[1]设置新值后,T2[1]的值为:%d\n",tmp);
Max(T2,tmp);
printf("T2的最大值为:%d\n",tmp);
Min(T2,tmp);
printf("T2的最小值为:%d\n",tmp);
if(DestroyTriplet(T2))
{
printf("T2的内存被释放!\n");
}
else
{
printf("T2释放内存失败!");
}
}
/* 定义并声明T,获得内存首址 */
int *T = InitTriplet(1,2,3);
/* 如果T,则说明内存分配成功 */
if(T)
{
printf("\n2.内存分配成功!\n");
printf("\nT表示的地址为%x,*T的值,也就是T[0]的值为:%d",T,(int)T[0]);
printf("\nT+1表示的地址为%x,*(T+1)的值,也就是T[1]的值为:%d",T+1,(int)T[1]);
printf("\nT+2表示的地址为%x,*(T+2)的值,也就是T[2]的值为:%d\n",T+2,(int)*(T+2));
}
/* 如果!T,则说明内存分配失败 */
else
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
//暂停以便输出
system("pause");
//无论如何,返回
return OK;
}
#include<stdio.h>
#include<stdlib.h>
/* 定义常量 增强可读性 */
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define OVERFLOW 3
/* 顺序存储结构 Triplet为int *类型 */
typedef int *Triplet;
/* 定义类型别名 增强可读性 */
typedef int Status;
typedef int Boolean;
/* 分配一个整形三元组的内存空间,返回该片内存空间首地址 */
int *InitTriplet(int v1,int v2,int v3)
{
int *T = (int *)malloc(3*sizeof(int));
if(!T)
exit(OVERFLOW);
T[0] = v1;
T[1] = v2;
T[2] = v3;
return T;
}
/* 采用引用参数 T是int *类型的Triplet的引用,改变T,也就是改变Triplet*/
Status InitTriplet2(Triplet &T,int v1,int v2,int v3)
{
T = (int *)malloc(3*sizeof(int));
if(!(T))
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
else
{
(T)[0] = v1;
(T)[1] = v2;
(T)[2] = v3;
}
return OK;
}
/* 销毁三元组 T为Triplet的别名(引用) */
Status DestroyTriplet(Triplet &T)
{
//如果T不为NULL,才释放
if(T)
{
free(T);
}
//设置T为0x00000000,也就是NULL
T = NULL;
return OK;
}
/* 用e返回T的第i个值 */
Status Get(Triplet T,int i,int &e)
{
if(i<1 || i>3) return ERROR;
e = T[i-1];
return OK;
}
/* 设置T的第i个值 */
Status Set(Triplet &T,int i,int e)
{
if(i<1 || i>3) return ERROR;
T[i-1] = e;
return OK;
}
/* 判断三元组是否升序排列 */
Boolean IsAscending(Triplet T)
{
return (T[0] <= T[1]) && (T[1] <= T[2]);
}
/* 判断三元组是否升序排列 */
Boolean IsDescending(Triplet T)
{
return (T[0] >= T[1]) && (T[1] >= T[2]);
}
/* 最大值用e返回 */
Status Max(Triplet T,int &e)
{
e = (T[0] >= T[1]) ? (T[0] >= T[2]?T[0]:T[2]):(T[1] >= T[2]?T[1]:T[2]);
return OK;
}
/* 最大值用e返回 */
Status Min(Triplet T,int &e)
{
e = (T[0] <= T[1]) ? (T[0] <= T[2]?T[0]:T[2]):(T[1] <= T[2]?T[1]:T[2]);
return OK;
}
/* 程序入口 */
int main(char *argc , char **argv)
{
int *T2 = NULL;
if(InitTriplet2(T2,4,5,6))
{
printf("1.内存分配成功!\n");
printf("\nT2表示的地址为%x,*T2的值,也就是T2[0]的值为:%d",T2,(int)T2[0]);
printf("\nT2+1表示的地址为%x,*(T2+1)的值,也就是T2[1]的值为:%d",T2+1,(int)T2[1]);
printf("\nT2+2表示的地址为%x,*(T2+2)的值,也就是T2[2]的值为:%d\n",T2+2,(int)*(T2+2));
int tmp;
Get(T2,2,tmp);
printf("T2[1]的值为:%d\n",tmp);
if(IsAscending(T2))
{
printf("T2升序排列\n");
}
else if(IsDescending(T2))
{
printf("T2降序排列\n");
}
else
{
printf("T2完全无序\n");
}
Set(T2,2,8);
Get(T2,2,tmp);
printf("T2[1]设置新值后,T2[1]的值为:%d\n",tmp);
Max(T2,tmp);
printf("T2的最大值为:%d\n",tmp);
Min(T2,tmp);
printf("T2的最小值为:%d\n",tmp);
if(DestroyTriplet(T2))
{
printf("T2的内存被释放!\n");
}
else
{
printf("T2释放内存失败!");
}
}
/* 定义并声明T,获得内存首址 */
int *T = InitTriplet(1,2,3);
/* 如果T,则说明内存分配成功 */
if(T)
{
printf("\n2.内存分配成功!\n");
printf("\nT表示的地址为%x,*T的值,也就是T[0]的值为:%d",T,(int)T[0]);
printf("\nT+1表示的地址为%x,*(T+1)的值,也就是T[1]的值为:%d",T+1,(int)T[1]);
printf("\nT+2表示的地址为%x,*(T+2)的值,也就是T[2]的值为:%d\n",T+2,(int)*(T+2));
}
/* 如果!T,则说明内存分配失败 */
else
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
//暂停以便输出
system("pause");
//无论如何,返回
return OK;
}