结构体指针

//////////////////////////////////////////////////////////////////////////结构体指针部分一////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
int main()
{
struct student
{
int score;
char name[128]; //定义字符形式的数组。

};//注意结构体后面具有分号

struct student stu1;
stu1.score=90;
strcpy(stu1.name, "小明"); //因为name是数组,应当用strcpy进行赋值。如果是指针可以直接进行赋值。
printf("输出学生的姓名成绩:%s:%d\n",stu1.name,stu1.score);
struct student *p ;// 注意指针的运用是采用->的形式进行操作 ,此时是野指针
p=(struct student *)malloc(sizeof(struct student)); //对指针进行空间的开辟
p->score=98;
strcpy (p->name, "不知道"); //通过函数进行字符串的赋值
printf("输出学生的名字,以及学生的成绩:%s:%d\n",p->name,p->score); //结构体指针的使用采用的是箭头
//注意结构体的指针,还可以直接的指向结构体的另一个对象
free(p);//实现对空间的释放,方式空间的泄露
p= &stu1; //注意指向的是结构体对象的地址,应当进行取地址的操作,注意在进行指针的赋值的时候,使用的依旧是=号,不是箭头。是指向某一个地址,并不是将地址给指针
printf("输出学生的名字,以及学生的成绩:%s:%d\n",p->name,p->score);//通过指针对结构体的对象stu1中的变量进行调用,注意是stu1对象操作后的结果
//此时结构体指针便是指向对象的地址,依然遵循指针的初衷
//研究结构体指针偏移量,从结果可以看出结构体指针偏移的量是整个结构之的大小。int+char[128]=132.
printf("打印偏移前的地址: %p\n",p);
p++;
printf("打印片偏移后的地址:%p\n",p);
return 0;
}

 ////////////////////////////////////////////////////////结构体指针部分二////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
struct student
{ int score;
char *name; // 注意此时是一个野指针,在使用的时候需要进行初始化。否则将会出现错误,非常的重要
};
struct student *initStuScore(int len) //定义一个返回值为strcut student 类型的函数。
{ struct student stu[5]; //创建五个对象,,也可以看成是对象的数组。
struct student *p=(struct student*)malloc(5*sizeof(struct student)); //开辟空间的大小。方式二;注意此处是形式变量,当程序执行以后就不存在,
int i;
for(i=0;i<len;i++) //通过对象的的总空间的大小,再除以空间的类型,求取i变量的范围
{ p->name=(char *)malloc(128); //对指针对象中的指针进行空间的开辟,不能将其放在循环的外面进行空间的申请,
//在循环的外部进行空间的申请,只是对指针所指向的第一个地址的元素进行了初始化,
//那么当指针发生偏移的时候,将会出现结构体指针指向的指针,未进行空间的开辟,也就是野指针,出现错误
printf("请输入学生的名字:\n");
scanf("%s",p->name); //对指针对象的指针进行赋值,此处是字符串,不用取地址,字符串表示地址
printf("请输入学生的成绩:\n");
scanf("%d",&(p->score)); //注意在进行给整形变量赋值的时候,应当进行取地址的方式
p++; //注意此时指针已经发生了偏转,注意此时指针的偏转是一个stu对象的空间大小,不是整个函数体
}
p=p-len; //通过这种的使用,对指针p的操作是正确的,可以正确的返回,注意函数返回的仅仅是局部变量的地址,并不是局部变量,局部变量将会消亡,因为是在堆中申请的内存空间
return p; //返回的仅仅是指针p的地址
}
struct student *findMax(struct student *p3 ,int len) //通过结构体的方式求出输入放入成绩的大小 ,注意,此时返回值是一个结构体的类型的指针,函数的形式参数也是一个结构体类型的指针
{struct student *Max; //定义结构体 ,该指针是局部的指针变量
int i;
Max=p3;// ,注意此时只是将结构体指针中的第一个地址给了结构体Max,注意指针的函数名就是指向第一个元素的地址
for(i=0;i<len;i++){
if(Max->score<p3->score){
Max=p3;
}
p3++; //指针的地址发生了偏移偏移的仅仅是局部的变量
}

return Max;

}
struct student *findmin(struct student *p4, int len) //注意形式参数一定要声明参数的类型
{ struct student *min; //定义结构体指针
int i;
min=p4;// ,注意此时只是将结构体指针中的第一个地址给了结构体min,注意指针的函数名就是指向第一个元素的地址
for(i=0;i<len;i++){
if(min->score>p4->score){
min=p4;

}
p4++; //指针的地址发生了偏移

}
return min;

}
void printMsg(struct student *p1, int len ) //此时的返回值是空,但是形式参数是结构体类型的指针,此时将结构体可以看作是一种变量的类型
{ int i;
int j=sizeof(p1); // 通过结构体的方式定义的变量,此时这种方式求解的是指针地址所占大小
printf("%d\n",j);
int k=sizeof(p1[0]); //此时求解的是结构体的大小。也就是结构中所有类型变量的占空间中总和
printf("%d\n",k);
for(i=0;i<len;i++)// 在进行传输的参数指针,再次对其进行求解大小的时候,将会出现错误
// for(i=0;i<sizeof(p1)/sizeof(p1[0]);i++); //不能使用这样的方式去求解指针的大小,这样只是求解的指针在该环境下占的空间
{
printf("输出学生的姓名以及分数:%s:%d\n",p1->name,p1->score);
p1++;
}
}

int findName(struct student *p5,char *name, int len){
int i;
for(i=0;i<len;i++){
if(strcmp(name,p5->name)==0){
// 注意: strcmp()函数其中具有两个参数,用于比较字符串的大小:
//如果第一个字符串大于第二个字符串,则返回值为正数
//如果第一个字符串小于第二个字符串,则返回的是负数
//如果第一个字符串等于第二个字符串,则返回的是0.
return 1;
}
p5++; //事实上指针最初指想的地址为首地址,此处进行指针的偏移,便是对指针指向的地址进行偏移。
}
return -1;
}

int main()
{ int len; //注意此处定义的全局的变量,其他的的函数也可以使用
printf("请输入总人数:");
scanf("%d",&len); //将输入放入len变量的地址,之所以此处需要取地址,是因为将输入的数字放入变量的地址中。
struct student *stu2 =initStuScore(len); //因为函数的返回值是结构体类型的指针
printMsg(stu2,len); //进行形式参数的传递,注意,在进行传参的时候,指针将stu2 地址进行拷贝。
//在函数体中对其进行如何的操作,都不会影响stu2指针的结果
struct student *Max1= findMax(stu2,len); //及逆行返回值的接收。
printf("Max=%s:%d\n",Max1->name,Max1->score); //Max1依旧是一种结构体指针,通过->的方式对结构体中的变量进行调用
struct student *Min=findmin(stu2,len);
printf("%s:%d\n",Min->name,Min->score);

if(findName(stu2,"小刘",len)==-1)
{
printf("对不起。没有找到此人!");
}
else
{
printf("恭喜你!找到啦");
}

/*
struct student stu[5]; //创建五个对象,,也可以看成是对象的数组。
//struct student *p=stu; //将指针指向对象的首地址,注意此时指针进行了初始化,所以不需要在进行空间的开辟等等 方式一:
struct student *p=(struct student*)malloc(5*sizeof(struct student)); //开辟空间的大小。方式二
int i;
for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++) //通过对象的的总空间的大小,再除以空间的类型,求取i变量的范围
{ p->name=(char *)malloc(128); //对指针对象中的指针进行空间的开辟,不能将其放在循环的外面进行空间的申请,
//在循环的外部进行空间的申请,只是对指针所指向的第一个地址的元素进行了初始化,
//那么当指针发生偏移的时候,将会出现结构体指针指向的指针,未进行空间的开辟,也就是野指针,出现错误
printf("请输入学生的名字:\n");
scanf("%s",p->name); //对指针对象的指针进行赋值,此处是字符串,不用取地址,字符串表示地址
printf("请输入学生的成绩:\n");
scanf("%d",&(p->score)); //注意在进行给整形变量赋值的时候,应当进行取地址的方式
p++; //注意此时指针已经发生了偏转,注意此时指针的偏转是一个stu对象的空间大小,不是整个函数体
}
for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++)
{p--;
printf("输出学生的成绩:\n");
printf("%s:%d\n",p->name,p->score);

}
*/
// 注意结构体指针依旧是一个指针,储存的依旧是地址,注意结构以在创建对象的时候,可以理解是创建一种结构体类型的变量,初始化,用的是等号,加上大括号
//注意结构体指针的变量名的大小指针的指针地址的大小,指针的首地址的标志,p[0],值的是整个结构体的大小。
return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////结构体大小的计算//////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
// 重点。重点 重点。
//1.结构体的偏移量必须是成员的大小的整数倍。
//2.结构体的大小必须是所有成员大小的整数被,(数组以及结构体除外,此处所说的结构体便是结构体中包含的结构体)
//满足上面的方式虽然很浪费空间,但是可以按照计算机的规则进行访问,这种对齐的方式加大了访问的效率
struct s1
{ char ch1;
char ch2;
int n; //此处地址的大小是4,前面的两个char之和为2,所以在偏移的时候,会自动的空出两个空间,这样前面的一共便是4,恰好是int是其整数倍
};
struct s2
{ char ca1; //1
int y; // 3+4
char ca2; //1

};
struct s3
{
char i;//1
int ca3; //4+3
char aa[12]; //10
};
struct s4
{
char i;
int ca4;
struct s{
char ch1;
char ch2;
int n;
};
float f;
};
struct s5
{
char ch5;
int i5;
union{
char ch;//注意:定义字符型的变量的时候,后边不要带数字
int ca5;
};

};
//#pragma pack(4) //指定的对齐的方式是4.虽然结构体中的最大占空间是8,注意此时的指定的对齐方是小于最大的占用空间。
struct s6
{
char ch6;
int i6;
float f;
double d; //所占的内存空间式8;
};
#pragma pack(10) //指定的对齐的方式是10.虽然结构体中的最大占空间是8,注意此时的指定的对齐方是小于最大的占用空间。,其后面的全部受其进行控制。
struct s7
{
char ch7;
int i7;
float f;
double d; //所占的内存空间式8;
};

int main()
{ printf("s1=%d\n",sizeof(struct s1)); //输出的结果是8,注意在进行计算结构体的时候,应当带上struct,结构体的标志
printf("s2=%d\n",sizeof(struct s2)); //此时输出的结果是12,但是我们逻辑分析结构体的大小是9,但是为了满足结构体的大小是所有成员的整数倍,所以结构体制动生成的到大小为12
printf("s3=%d\n",sizeof(struct s3));//输出的结果为20,满足前面两个数的整数倍,但是不满足数组,也就是说,结构体的大小,不需要是数组的整数倍
printf("s4=%d\n",sizeof(struct s4));//此时输出的大小是20,明显不是里面所包含的结构体大小8的整数倍,所以当结构体中,定义了结构体是,其所包含的结构体只能看做式 int 或者char等类型,不能看作式一个整体
printf("s5=%d\n",sizeof(struct s5));// 此时输出的结果式12,
printf("s6=%d\n",sizeof(struct s6));//注意此处输出的结果是20,如果以8为对齐的方式,那么因该是24,所以此处的对齐的方式是4.
printf("s7=%d\n",sizeof(struct s7)); //注意此时输出的结果不是30,而是24,不是按照规定的对齐方式。因为此处规定的对齐大于结构体的中最大的空间占用。那么此时便是以结构体中的最大的空间占用作为对齐的方式。。
//重点。
return 0;
}

 /////////////////////////////////////////////////////////////////////////////////////////////指针变量空间的申请//////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
int main()
{ //int a[3];
int *a=(int*)malloc(3*sizeof(int));
int i;
for(i=0;i<3;i++){
a[i]=i;// 此处是将指针。
}
for(i=0;i<3;i++){

printf("通过数组的变量名打印对数组进行遍历:%d\n",a[i]);

}
int n;
printf("请输入需要输入放入申请int的空间大小的个数");
scanf("%d",&n);
int arry[n];// 通过输入值,开辟数组空间的大小
//int *arry= (int*)malloc(n*sizeof(int)); //此处是申请空间,通过malloc的方法。此处进行了强制的转换(int*)
printf("打印n的值:%d\n",n);
if(arry==NULL){
printf("空间内存申请失败");
}

printf("请输入学生的成绩:\n");
for(i=0;i<n;i++){
scanf("%d",&arry[i]);// 此处将变量i的值,依次的存放在数组这之中,在通过scanf()在输入的时候具有严格的格式,不要在里面输入其他任何的东西。否则将会引起不必要的错误
printf("打印i的值:%d\n",i);


}
for(i=0;i<n;i++){
//printf("通过指针的方式访问元素指针的元素: %d\n",*arry++);
printf("通过数组的方式,访问数组中的元素:%d\n",arry[i]);
}

//printf("通过指针的方式访问元素指针的元素: %d\n",*arry++);

return 0;
}
/*
内存泄漏的问题。
while(1)
{


sleep(1);
int *p=(int*)malloc(1024);// 注意在LinuX系统同只有程序执行完毕以后才会将空间的内存进行释放,程序没有执行结束空间的内存将不会释放,可能出现死机的现象
//通常采用free()函数及逆行合理的空间及逆行释放
//避免的方法
free(p);// 注意此时的指针式野指针,指向的地址是由系统随机进行分配的
p=NULL;//此时p指针便不再是野指针。
// 通常指针初始化便是这样 int *p=NULL;

}
*/

 

posted @ 2021-03-10 18:02  LInguistic-零点  阅读(1069)  评论(0编辑  收藏  举报