C语言结构体详解

简介: C语言结构体详解

结构体有什么用?

我们学习结构体之前需要知道结构体有什么用。举个例子,假如我现在需要将100个学生的信息录入教学系统。他们有年龄,性别,名字。我们进行编程的时候。不可能一一进行变量创建。那样太麻烦了。


那么我们就可以创建一个结构体,这个结构体类型里面包含年龄,性别,名字。这样,我们可以把小明,小红,小华都设置为这个类型的结构体。然后再对这个结构体赋值就可以了。


结构体声明

正常的结构体声明

结构体声明有两种方法

第一种是struct Stu s2。需要注意,struct一定要写上!

第二种方法就是在声明结构体的时候,}后面加上需要设置的结构体变量


//现在我们建立了一个结构体类型,这个结构体类型名字叫做Stu
//s3,s4,s5,s6为全局变量,s1,s2是局部变量,但是他们都是同一种类型的结构体变量
struct Stu
{
  char name[20];//名字
  char tele[12];//电话
  char sex[10];//性别
  int age;
} s4,s5,s6;   //注意,这里的;不能少
struct Stu s3;//全局变量
int main()
{
  //创建的结构体变量
  struct Stu s1;//注意,这里的struct不能少
  struct Stu s2;
  return 0;
}


匿名结构体

匿名结构体只有在创建的时候可以建立变量

(1)匿名结构体就是在创建结构体的时候,struct后面不加名字。个人不推荐使用匿名结构体,因为你创建了结构体之后,就不能再次创建该结构体的变量了。


(2)以下面这个为例子,我们struct后面没有增加名字。那么现在就只有sa这一个变量是属于该结构体类型变量。不能再次建立该类型的结构体变量了。


struct
{
  int a;
  char c;
}sa;  //这里一定要加sa,否则你接下来不能再次建立该结构体类型的变量了
int main()
{
    struct s1;   //这样是不可以的
    return 0;
}

两个相同的匿名结构体,编译器会认为是不相同

(1)我们都知道,char型指针如果指向一个int型数据。编译器会报警告。

int main()
{
  int x;
  char* y = &x;  //警告
  return 0;
}

(2)匿名结构体依旧如此,我们看起来长得一样的两个匿名结构体,编译器也会将他们看成是两个不同的类型。

struct
{
  int a;
  char c;
}sa;
struct
{
  int a;
  char c;
}* psa;
int main()
{
  psa = &sa;  //警告,编译器会把上面的两个声明当成完全不同的两个类型
  return 0;
}


结构体自引用

结构体自引用结构体

结构体创建变量的时候,创建的变量中有一个是自己,类似于递归。(但是不同!)

struct Node
{
  int data;//4
  struct Node n;  //这样是错误的
};


上面这一串代码明显是错误的。因为,假如他是正确的,那么他的大小sizeof(struct Node)是多少呢?很显然,无法确认。

结构体自引用结构体指针

(1)数据结构中有一个东西叫做链表。


(2)因为我们平常使用的数据都是依次按照顺序连接的,但是,如果我现在需要在这一堆数据arr的中间假如一个其他数据a。那么现在我就需要将arr中间的数据改为a,然后更改的数据都往后移动。这样明显很麻烦。


(3)那么我们可以利用链表的方式,比如说,现在我们有一个数据链arr1。每一个数据指向后面这个数字。那么,我现在需要在中间增加一个数据b,只需要将插入前面这个数据指向b,然后b指向插入后面这个数据即可。


(4)那么,方法如下


struct Node
{
 int data;
 struct Node* next;
};

此时sizeof(struct Node)为多少呢?如果是32位的系统下,是8个字节。因为int是4个字节,后面这个指针在32位系统下也是4个字节。

typedef与结构体


只创建一个名称

因为我们每次创建一个变量需要写成 struct Stu s1;很明显太麻烦了。于是我们可以使用typedef与结构体给结构体起一个别名。

typedef struct Node
{
  double d;
  int data;
}Node;
int main()
{
  //下面这两个等价
  struct Node n1;
  Node n2;
  return 0;
}

创建两个变量名

有时候我们会看见typedef与结构体之后会有两个名字,这个是怎么会是呢?

这样就同时建立了两种类型,一种是Node型的结构体,一个是Node型的结构体指针。

// 在重命名结构体时,命名了两种:Node结构体类型,*pNode结构体指针类型
typedef struct Node
{
  double d;
  int data;
}Node,*pNode;
int main()
{
  pNode = &Node;
  return 0;
}


注意事项

虽然我们有typedef,但是如果需要链表那种形式的创建,还是有讲究的地方。我们看下面这一段代码。

因为在我typedef之前,你就已经使用了Node了。那么编译器就不会认识Node*。

/***** 错误写法 *****/
typedef struct 
{
  double d;
  int data;//4
  Node* next;//4/8
}Node;
/***** 正确写法 *****/
typedef struct Node
{
  double d;
  int data;//4
  struct Node* next;//4/8
}Node;


赋值

顺序赋值

对于结构体只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值

/******这样是可以的,在定义变量的时候就初始化了*******/
    struct book s1={ "guojiajiaoyun", "yuwen",22.5};
/******这种就不行了,在定义变量之后,若再要对变量的成员赋值,那么只能单个赋值了*******/
    struct book s1;
    //这样就是不行的,只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值
    s1={"guojiajiaoyun","yuwen",22.5  };
    s1.title = "yuwen";//只能单个赋值;


自定义顺序赋值

我们很多时候都是按照顺序来赋值的,但是如果是“.成员”的格式来写,就是可以自定义顺序赋值,这个在Linux内核中是非常常见的。

/*******顺序赋值*********/
typedef struct 
{
  double d;
  int data;//4
}Node;
int main(void)
{
  Node a = {5,0.0};
  return 0;
}
/*******自定义顺序赋值*********/
typedef struct 
{
  double d;
  int data;//4
}Node;
int main(void)
{
  Node a = {
    .data = 5,
    .d    = 0.0
  };
  return 0;
}


引用数据

我们直接写上'.'进行数据引用

struct T
{
  double weight;
  short age;
};
struct S
{
  char c;
  struct T st;
  int a;
  double d;
  char arr[20];
};
int main()
{
  struct S s = { 'c', {55.6, 30}, 100, 3.14, "hello bit" };
  printf("%c %d %lf %s\n", s.c, s.a, s.d, s.arr);
  printf("%lf\n", s.st.weight);
  return 0;
}
目录
相关文章
|
5天前
|
存储 C语言
向函数传递结构体: C语言中的结构体参数传递详解
向函数传递结构体: C语言中的结构体参数传递详解
18 0
|
6天前
|
存储 编译器 Linux
C语言(12)----结构体
C语言(12)----结构体
16 1
TU^
|
11天前
|
编译器 Linux C语言
C语言之结构体
C语言中的结构体是一种用户自定义的数据类型,它允许将不同类型的数据组合在一起,形成一个新的数据类型。
TU^
25 0
|
11天前
|
存储 C语言
C语言的结构体
C语言的结构体
22 0
|
13天前
|
存储 C语言
C语言进阶⑮(自定义类型)(结构体+枚举+联合体)(结构体实现位段)(下)
C语言进阶⑮(自定义类型)(结构体+枚举+联合体)(结构体实现位段)
21 0
|
3天前
|
存储 算法 C语言
C语言中的结构体与共用体:深入探索与应用
C语言中的结构体与共用体:深入探索与应用
9 0
|
5天前
|
存储 大数据 程序员
实验验证C语言中结构体与共用体的差异
实验验证C语言中结构体与共用体的差异
15 0
|
5天前
|
存储 C语言
C语言中的结构体与函数传递技术详解
C语言中的结构体与函数传递技术详解
14 1
|
5天前
|
存储 安全 C语言
C语言中的共用体与结构体的区别
C语言中的共用体与结构体的区别
19 3
|
6天前
|
编译器 C语言 C++
C语言进阶:结构体的声明
C语言进阶:结构体的声明