Linux C 之 结构体

1 产生及意义

2 类型描述

struct 结构体名

{

数据类型 成员1;

数据类型 成员2;

数据类型 成员3;

...............

};

3 嵌套定义

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32


struct simple_st
{
    int i,j;
    float f;
    char ch;
    
};

struct birthday_st
{
    int year;
    int month;
    int day;
};//定义


struct student_st
{
    int id; 
    char name[NAMESIZE];
    struct birthday_st birth;//嵌套方式一
    struct math
   {
      char name[];
      int before score;
      int average;
   }math_inf;//嵌套方式二

    int chinese;
    
};


int main()
{
    
}

4 定义变量(变量、数组、指针),初始化及成员引用

成员引用:变量名 .成员名

指针名 ->成员名

(*指针) .成员名

注意:只能在初始化时全部赋值,其他情况下需要单个引用的方式赋值

初始化及成员引用方法一:

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32


struct simple_st
{
    int i;
    float f;
    char ch;

};


int main()
{
    //TYPE NAME = VALUE;

    struct simple_st a = {123,456.789,'a'};//赋值

    a.i = 112233;//修改值

    printf("%d\t%f\t%c\n",a.i,a.f,a.ch);//打印
   
}

初始化及成员引用方法二:
    
#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32


struct birthday_st
{
    int year;
    int month;
    int day;
};


struct student_st
{
    int id;
    char name[NAMESIZE];
    struct birthday_st birth;
    int math;
    int chinese;

};


int main()
{
    //TYPE NAME = VALUE;



     struct student_st stu = {10011,"Alan",{2011,11,11},98,97};//全部赋值
   

     printf("%d %s %d-%d-%d %d         %d\n",stu.id,stu.name,stu.birth.year,stu.birth.month,stu.birth.day,stu.math,stu.chinese);//变量名.成员名方式打印
     
 
}
初始化及成员引用方法三:

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32


struct birthday_st
{
    int year;
    int month;
    int day;
};


struct student_st
{
    int id;
    char name[NAMESIZE];
    struct birthday_st birth;
    int math;
    int chinese;

};


int main()
{
    //TYPE NAME = VALUE;
  
    struct student_st stu = {.math = 98,.chinese = 97};// .成员名 (部分赋值)  
    printf("%d %d",stu.math,stu.chinese);//打印

}

初始化及成员引用方法四:

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32



struct birthday_st
{
    int year;
    int month;
    int day;
};


struct student_st
{
    int id;
    char name[NAMESIZE];
    struct birthday_st birth;
    int math;
    int chinese;

};


int main()
{
    //TYPE NAME = VALUE;


     struct student_st stu = {10011,"Alan",{2011,11,11},98,97};//赋值
     struct student_st *p = &stu;//定义一个指向stu的结构体类型的指针
     
      printf("%d %s %d-%d-%d %d %d\n",p->id,p->name,p->birth.year,p->birth.month,p->birth.day,p->math,p->chinese);// 指针名 ->成员名 打印
      printf("%d %s %d-%d-%d %d %d\n",(*p).id,(*p).name,(*p).birth.year,(*p).birth.month,(*p).birth.day,(*p).math,(*p).chinese);// (*指针名).成员名  打印

}

结构体数组:

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32

struct birthday_st
{
    int year;
    int month;
    int day;
};


struct student_st
{
    int id;
    char name[NAMESIZE];
    struct birthday_st birth;
    int math;
    int chinese;

};


int main()
{
    //TYPE NAME = VALUE;
     int i;

     struct student_st *p;//定义一个指向结构体的指针
     struct student_st arr[2] = {{10011,"Alan",{2011,11,11},98,97},{10012,"Dasiy",{2012,11,11},90,99}};//赋值
     p = &arr[0]; //p = arr;指针指向数组的起始地址

      for(i = 0 ; i < 2 ; i++,p++)//循环打印,p++ ->p = p+1
      {
            printf("%d %s %d-%d-%d %d %d\n",p->id,p->name,p->birth.year,p->birth.month,p->birth.day,p->math,p->chinese);//打印
      }

}

5 占用内存空间大小

根据成员位置分配线性存储内存

结构体地址对齐:

add % sizeof(数据类型) linux默认4字节对齐(结构体整体对齐)

例如,结构体中第一个成员为int 型,占用四个字节,即地址的0,1,2,3

结构体的第二个成员为char型,从第四个地址开始,即arr = 4, arr % sizeof(char) = 0 ,地址对齐可以存放,该数据就存放在4

结构体的三个成员为float型 ,从第五个地址开始,即arr = 5,arr % sizeof(float) ,即5 % 4 = 1(不满足),地址加一,

6 % 4 = 2(不满足),7 % 4 = 3(不满足),地址加一,8 % 4 = 0(满足要求),所以该float型的值从地址8开始,即地址5,6,7没有内容

#include <stdio.h>
#include <stdlib.h>


 struct simpl_st
    {
        int i;
        float f;
        char ch;
    };//定义结构体


int main()
{
   struct simpl_st st;//初始化
   struct simpl_st *p = &st;//定义一个结构体指针指向结构体

   printf("sizeof(st) = %d\n",sizeof(st));//打印结构体占用的字节数
   printf("sizeof(p) =  %d\n",sizeof(p));//打印指针占用的字节数

   exit(0);
}

在跨网络传输时,不能使用地址对齐

因为传输端与接收端的地址对齐规则可能不一样

解决办法:使用宏 __ attribute__((packed))

#include <stdio.h>
#include <stdlib.h>


 struct simpl_st
    {
        int i; //4
        float f;//4
        char ch;//1
    }__attribute((packed));//地址不对齐,4+4+1 = 9


int main()
{
   struct simpl_st st;
   struct simpl_st *p = &st;

   printf("sizeof(st) = %d\n",sizeof(st));打印结构体占用的字节数
   printf("sizeof(p) =  %d\n",sizeof(p));//打印

   exit(0);
}

6 函数传参(值 ,地址)

值传参(结构体):

#include <stdio.h>
#include <stdlib.h>


 struct simpl_st
    {
        int i;
        float f;
        char ch;
    };


void func(struct simpl_st b)//值接受,重新定义一片空间来接受与结构体一样大小的内容,比较浪费内容
{
    printf("sizeof(b) = %d\n",sizeof(b));//形参的大小为12,与结构体一样
}

int main()
{
   struct simpl_st st;
   struct simpl_st *p = &st;

   printf("sizeof(st) = %d\n",sizeof(st));
   printf("sizeof(p) =  %d\n",sizeof(p));

   func(st);//传入结构体名

   exit(0);
}

用指针传参(结构体)(节省内存)

#include <stdio.h>
#include <stdlib.h>


struct simpl_st//定义结构体
{
        int i;
        float f;
        char ch;
};


void func(struct simpl_st *b)//指针形参
{
    printf("sizeof(b) = %d\n",sizeof(b));//打印形参大小,为8,当传入的结构体比较大时,指针传参比值传参更省内存
}

int main()
{
   struct simpl_st st;
   struct simpl_st *p = &st;

   printf("sizeof(st) = %d\n",sizeof(st));
   printf("sizeof(p) =  %d\n",sizeof(p));//sizeof(&st)

   func(p);//指针传参

   exit(0);
}

微型学生管理系统

#include <stdio.h>
#include <stdlib.h>

#define NAMESIZE 32

struct student_st
{
    int id;
    char name[NAMESIZE];
    int math;
    int chinese;
};//建立学生信息结构体



void mune(void)
{
    printf("\n1 set\t2  changname\t3  show\n\n");
    printf("Please enter the num you want to choice(enter q for quit):\n\n");
}//模式选择菜单

void stu_set(struct student_st *p,struct student_st *q)
{
    *p = *q;

}//结构体赋值


void stu_changename(struct student_st *p,const char *newname)
{

    strcpy(p->name,newname);
}//修改名字


void stu_show(struct student_st *p)
{
    printf("%d %s %d %d\n\n",p->id,p->name,p->math,p->chinese);
}//打印信息

int main()
{
    int ret,choice,i;
    char newname[NAMESIZE];
    struct student_st stu,tmp;

   do
  {

    mune();
    ret = scanf("%d",&choice);
    if(ret != 1)
        break;




        switch(choice)
        {

            case 1:
                printf("\nPlease enter the student's information :[id][name][math][chinese]:\n");
                scanf("%d%s%d%d",&tmp.id,&tmp.name,&tmp.math,&tmp.chinese);
                stu_set(&stu,&tmp);
                    break;

            case 2:
                printf("\nPlease enter the name you want to change:[name]:\n");
                scanf("%s",newname);
                stu_changename(&stu,newname);
                    break;


            case 3:
                printf("\n");
                stu_show(&stu);
                break;


            default:
                printf("Please enter the right number(as 1,2,3)!\n");
                exit(-1);

          }
          sleep(1);
    }while(1);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,C语言结构体的地址传递与其他类型的变量的地址传递方式相同。可以通过将结构体变量的地址作为参数传递给函数来实现结构体的地址传递。例如,可以定义一个函数,接受一个指向结构体的指针作为参数,并在函数内部对结构体进行操作。 以下是一个示例代码: ```c #include <stdio.h> struct student { char name\[20\]; char sex; int num; }; void printStudent(struct student *s) { printf("Name: %s\n", s->name); printf("Sex: %c\n", s->sex); printf("Number: %d\n", s->num); } int main() { struct student s = { "zhangsan", 'm', 123 }; printStudent(&s); // 将结构体的地址传递给函数 return 0; } ``` 在上述代码中,我们定义了一个`printStudent`函数,它接受一个指向`struct student`类型的指针作为参数。在`main`函数中,我们创建了一个`struct student`类型的变量`s`,然后将其地址传递给`printStudent`函数。在`printStudent`函数内部,我们使用指针操作符`->`来访问结构体成员,并打印出结构体的内容。 通过这种方式,我们可以在函数内部对结构体进行修改,并且这些修改将在函数外部保持有效。这是因为我们传递的是结构体的地址,而不是结构体的副本。 #### 引用[.reference_title] - *1* *2* *3* [C语言 结构体](https://blog.csdn.net/qq_62316056/article/details/124313297)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值