zoukankan      html  css  js  c++  java
  • 结构体指针

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

    #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 ",stu1.name,stu1.score);
    struct student *p ;// 注意指针的运用是采用->的形式进行操作 ,此时是野指针
    p=(struct student *)malloc(sizeof(struct student)); //对指针进行空间的开辟
    p->score=98;
    strcpy (p->name, "不知道"); //通过函数进行字符串的赋值
    printf("输出学生的名字,以及学生的成绩:%s:%d ",p->name,p->score); //结构体指针的使用采用的是箭头
    //注意结构体的指针,还可以直接的指向结构体的另一个对象
    free(p);//实现对空间的释放,方式空间的泄露
    p= &stu1; //注意指向的是结构体对象的地址,应当进行取地址的操作,注意在进行指针的赋值的时候,使用的依旧是=号,不是箭头。是指向某一个地址,并不是将地址给指针
    printf("输出学生的名字,以及学生的成绩:%s:%d ",p->name,p->score);//通过指针对结构体的对象stu1中的变量进行调用,注意是stu1对象操作后的结果
    //此时结构体指针便是指向对象的地址,依然遵循指针的初衷
    //研究结构体指针偏移量,从结果可以看出结构体指针偏移的量是整个结构之的大小。int+char[128]=132.
    printf("打印偏移前的地址: %p ",p);
    p++;
    printf("打印片偏移后的地址:%p ",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("请输入学生的名字: ");
    scanf("%s",p->name); //对指针对象的指针进行赋值,此处是字符串,不用取地址,字符串表示地址
    printf("请输入学生的成绩: ");
    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 ",j);
    int k=sizeof(p1[0]); //此时求解的是结构体的大小。也就是结构中所有类型变量的占空间中总和
    printf("%d ",k);
    for(i=0;i<len;i++)// 在进行传输的参数指针,再次对其进行求解大小的时候,将会出现错误
    // for(i=0;i<sizeof(p1)/sizeof(p1[0]);i++); //不能使用这样的方式去求解指针的大小,这样只是求解的指针在该环境下占的空间
    {
    printf("输出学生的姓名以及分数:%s:%d ",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 ",Max1->name,Max1->score); //Max1依旧是一种结构体指针,通过->的方式对结构体中的变量进行调用
    struct student *Min=findmin(stu2,len);
    printf("%s:%d ",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("请输入学生的名字: ");
    scanf("%s",p->name); //对指针对象的指针进行赋值,此处是字符串,不用取地址,字符串表示地址
    printf("请输入学生的成绩: ");
    scanf("%d",&(p->score)); //注意在进行给整形变量赋值的时候,应当进行取地址的方式
    p++; //注意此时指针已经发生了偏转,注意此时指针的偏转是一个stu对象的空间大小,不是整个函数体
    }
    for(i=0;i<sizeof(stu)/sizeof(stu[0]);i++)
    {p--;
    printf("输出学生的成绩: ");
    printf("%s:%d ",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 ",sizeof(struct s1)); //输出的结果是8,注意在进行计算结构体的时候,应当带上struct,结构体的标志
    printf("s2=%d ",sizeof(struct s2)); //此时输出的结果是12,但是我们逻辑分析结构体的大小是9,但是为了满足结构体的大小是所有成员的整数倍,所以结构体制动生成的到大小为12
    printf("s3=%d ",sizeof(struct s3));//输出的结果为20,满足前面两个数的整数倍,但是不满足数组,也就是说,结构体的大小,不需要是数组的整数倍
    printf("s4=%d ",sizeof(struct s4));//此时输出的大小是20,明显不是里面所包含的结构体大小8的整数倍,所以当结构体中,定义了结构体是,其所包含的结构体只能看做式 int 或者char等类型,不能看作式一个整体
    printf("s5=%d ",sizeof(struct s5));// 此时输出的结果式12,
    printf("s6=%d ",sizeof(struct s6));//注意此处输出的结果是20,如果以8为对齐的方式,那么因该是24,所以此处的对齐的方式是4.
    printf("s7=%d ",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 ",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);
    if(arry==NULL){
    printf("空间内存申请失败");
    }

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


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

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

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


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

    }
    */

  • 相关阅读:
    WSS 扩展文件夹的属性如何给文件夹添加扩展字段
    SharePoint 打开文档附件不弹出提示框
    SharePoint2010 安装时报“未能启动数据库服务 MSSQL$Sharepoint"解决办法
    常见问题
    sharepoint 关于pdf格式在线打开
    ASP.NET 2.0 连接Sql Server 2005报错 [DBNETLIB][ConnectionOpen (Invalid Instance()).]无效的连线。
    <转>SQL Server 2008 R2十大新特性解析
    windows查看端口占用情况
    SQL Server适用脚本收集一
    信息系统中用户的域AD认证功能
  • 原文地址:https://www.cnblogs.com/Nic-zhang/p/14513372.html
Copyright © 2011-2022 走看看