参考摘抄学习来自:
- C 结构体
- C语言必学知识点 "结构体"详细解析!
- C 语言之结构体最全面总结
- C typedef
文章目录
- 1 定义
- 2 初始化
- 3 结构体大小的计算
- 4 访问结构成员
- 5 结构作为函数参数
- 6 指向结构的指针
- 7 结构体数组
- 8 动态申请结构体
1 定义
它允许您存储不同类型的数据项。
结构体中的数据成员可以是基本数据类型(如 int、float、char 等),也可以是其他结构体类型、指针类型等。
struct tag { member-listmember-list member-list ...
} variable-list ;
tag 是结构体标签。
member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。
在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。以下为实例:
eg
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct
{int a;char b;double c;
} s1;//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{int a;char b;double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;//也可以用typedef创建新类型
typedef struct
{int a;char b;double c;
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
结构体嵌套
//此结构体的声明包含了其他的结构体
struct COMPLEX
{char string[100];struct SIMPLE a;
};//此结构体的声明包含了指向自己类型的指针
struct NODE
{char string[100];struct NODE *next_node;
};
C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。下面的实例为单字节数字定义了一个术语 BYTE:
typedef unsigned char BYTE;
在这个类型定义之后,标识符 BYTE 可作为类型 unsigned char 的缩写,例如:
BYTE b1, b2;
按照惯例,定义时会大写字母,以便提醒用户类型名称是一个象征性的缩写,但您也可以使用小写字母,如下:
typedef unsigned char byte;
您也可以使用 typedef 来为用户自定义的数据类型取一个新的名字。例如,您可以对结构体使用 typedef 来定义一个新的数据类型名字,然后使用这个新的数据类型来直接定义结构变量
2 初始化
#include <stdio.h>struct Books
{char title[50];char author[50];char subject[100];int book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};int main()
{printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}
output
title : C 语言
author: RUNOOB
subject: 编程语言
book_id: 123456
3 结构体大小的计算
#include <stdio.h>struct Person {char name[20];int age;float height;
};int main() {struct Person person;printf("name size: %zu\n", sizeof(person.name));printf("age size: %zu\n", sizeof(person.age));printf("height size: %zu\n", sizeof(person.height));printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));return 0;
}
output
name size: 20
age size: 4
height size: 4
结构体 Person 大小为: 28 字节
再看看下面这个例子
#include <stdio.h>int main(void)
{struct A{char a;int b;char c;} a = {'a', 10, 'o'};printf("size of a = %d\n", sizeof(a.a));printf("size of b = %d\n", sizeof(a.b));printf("size of c = %d\n", sizeof(a.c));printf("size of a = %d\n", sizeof(a));return 0;
}
output
size of a = 1
size of b = 4
size of c = 1
size of a = 12
#include <stdio.h>int main(void)
{struct A{char a;char c;int b;} a = {'a', 'o', 10};printf("size of a = %d\n", sizeof(a.a));printf("size of c = %d\n", sizeof(a.c));printf("size of b = %d\n", sizeof(a.b));printf("size of a = %d\n", sizeof(a));return 0;
}
output
size of a = 1
size of c = 1
size of b = 4
size of a = 8
存在内存对齐现象
在C语言中,内存对齐(Memory Alignment)是一个重要的概念,它指的是数据在内存中按照一定的规则进行排列,以提高内存的访问效率。不同的硬件平台对内存访问有不同的要求,如果数据没有按照这些要求来对齐,可能会导致性能下降,甚至在某些平台上引发硬件异常。
为什么要内存对齐?
- 性能优化:现代计算机体系结构通常通过内存对齐来提高内存访问速度。这是因为硬件可能设计为以特定的字节边界(如4字节、8字节等)来高效地访问内存。
- 平台兼容性:不同的硬件平台对内存对齐的要求可能不同。遵循内存对齐的规则可以确保程序在不同平台上的兼容性。
内存对齐的规则
- 自然对齐:数据的存储起始地址是数据本身大小的整数倍。例如,int类型(假设为4字节)的变量应该存储在4的倍数地址上。
- 结构体对齐:结构体中的成员变量和整个结构体本身都会受到对齐规则的影响。结构体成员的对齐通常遵循其自然对齐规则,而结构体本身的对齐则可能由编译器或编译器的特定选项决定。
- 编译器指令:大多数编译器提供了控制对齐的指令或选项,如GCC的
__attribute__((aligned(n)))
和MSVC的#pragma pack(n)
。
4 访问结构成员
成员访问运算符(.)
#include <stdio.h>
#include <string.h>struct Books
{char title[50];char author[50];char subject[100];int book_id;
};int main( )
{struct Books Book1; /* 声明 Book1,类型为 Books */struct Books Book2; /* 声明 Book2,类型为 Books *//* Book1 详述 */strcpy( Book1.title, "C Programming");strcpy( Book1.author, "Nuha Ali");strcpy( Book1.subject, "C Programming Tutorial");Book1.book_id = 6495407;/* Book2 详述 */strcpy( Book2.title, "Telecom Billing");strcpy( Book2.author, "Zara Ali");strcpy( Book2.subject, "Telecom Billing Tutorial");Book2.book_id = 6495700;/* 输出 Book1 信息 */printf( "Book 1 title : %s\n", Book1.title);printf( "Book 1 author : %s\n", Book1.author);printf( "Book 1 subject : %s\n", Book1.subject);printf( "Book 1 book_id : %d\n", Book1.book_id);/* 输出 Book2 信息 */printf( "Book 2 title : %s\n", Book2.title);printf( "Book 2 author : %s\n", Book2.author);printf( "Book 2 subject : %s\n", Book2.subject);printf( "Book 2 book_id : %d\n", Book2.book_id);return 0;
}
output
Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
#include <stdio.h>
#include <string.h>struct Person {int age;float height;
};struct Birthday{char name[20];struct Person person;
};int main() {struct Birthday birthday;strcpy(birthday.name, "Bryant");birthday.person.age = 18;birthday.person.height = 171;printf("name:%s, age:%d, height:%f\n", birthday.name, birthday.person.age, birthday.person.height);return 0;
}
output
name:Bryant, age:18, height:171.000000
5 结构作为函数参数
#include <stdio.h>
#include <string.h>struct Books
{char title[50];char author[50];char subject[100];int book_id;
};/* 函数声明 */
void printBook( struct Books book );
int main( )
{struct Books Book1; /* 声明 Book1,类型为 Books */struct Books Book2; /* 声明 Book2,类型为 Books *//* Book1 详述 */strcpy( Book1.title, "C Programming");strcpy( Book1.author, "Nuha Ali");strcpy( Book1.subject, "C Programming Tutorial");Book1.book_id = 6495407;/* Book2 详述 */strcpy( Book2.title, "Telecom Billing");strcpy( Book2.author, "Zara Ali");strcpy( Book2.subject, "Telecom Billing Tutorial");Book2.book_id = 6495700;/* 输出 Book1 信息 */printBook( Book1 );/* 输出 Book2 信息 */printBook( Book2 );return 0;
}
void printBook( struct Books book )
{printf( "Book title : %s\n", book.title);printf( "Book author : %s\n", book.author);printf( "Book subject : %s\n", book.subject);printf( "Book book_id : %d\n", book.book_id);
}
output
Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700
#include <stdio.h>struct Student{int age;
};void test(struct Student stu){printf("test 修改前的值:%d\n", stu.age);stu.age = 10;printf("test 修改后的值:%d\n", stu.age);
}int main()
{struct Student student;student.age = 30;printf("main 修改前的值:%d\n", student.age);test(student);printf("main 修改后的值:%d\n", student.age);return 0;
}
output
main 修改前的值:30
test 修改前的值:30
test 修改后的值:10
main 修改后的值:30
可以看到仅改变了形参,实际值没有改变,传结构体指针就没问题(见下节)
#include <stdio.h>struct Student{int age;
};void test(struct Student* stu){printf("test 修改前的值:%d\n", stu->age);stu->age = 10;printf("test 修改后的值:%d\n", stu->age);
}int main()
{struct Student student;student.age = 30;printf("main 修改前的值:%d\n", student.age);test(&student);printf("main 修改后的值:%d\n", student.age);return 0;
}
output
main 修改前的值:30
test 修改前的值:30
test 修改后的值:10
main 修改后的值:10
6 指向结构的指针
#include <stdio.h>
#include <string.h>struct Student{char name[20];int age;
};int main()
{struct Student student;student.age = 20;strcpy(student.name, "Bryant");printf("name: %s, age: %d\n", student.name, student.age);struct Student *p = &student;printf("name: %s, age: %d\n", p->name, p->age);printf("name: %s, age: %d\n", (*p).name, (*p).age);return 0;
}
output
name: Bryant, age: 20
name: Bryant, age: 20
name: Bryant, age: 20
#include <stdio.h>
#include <string.h>struct Books
{char title[50];char author[50];char subject[100];int book_id;
};/* 函数声明 */
void printBook( struct Books *book );
int main( )
{struct Books Book1; /* 声明 Book1,类型为 Books */struct Books Book2; /* 声明 Book2,类型为 Books *//* Book1 详述 */strcpy( Book1.title, "C Programming");strcpy( Book1.author, "Nuha Ali"); strcpy( Book1.subject, "C Programming Tutorial");Book1.book_id = 6495407;/* Book2 详述 */strcpy( Book2.title, "Telecom Billing");strcpy( Book2.author, "Zara Ali");strcpy( Book2.subject, "Telecom Billing Tutorial");Book2.book_id = 6495700;/* 通过传 Book1 的地址来输出 Book1 信息 */printBook( &Book1 );/* 通过传 Book2 的地址来输出 Book2 信息 */printBook( &Book2 );return 0;
}
void printBook( struct Books *book )
{printf( "Book title : %s\n", book->title);printf( "Book author : %s\n", book->author);printf( "Book subject : %s\n", book->subject);printf( "Book book_id : %d\n", book->book_id);
}
output
Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700
7 结构体数组
#include <stdio.h>
#include <string.h>struct Person {char name[20];int age;float height;
}person[3]={{"Bryant", 19, 178}, {"Chole", 18, 167}};int main() {for(int i=0; i<2; i++)printf("name:%s, age:%d, height:%f\n", person[i].name, person[i].age, person[i].height);return 0;
}
output
name:Bryant, age:19, height:178.000000
name:Chole, age:18, height:167.000000
8 动态申请结构体
结构体也可以在堆里面动态申请
#include <stdio.h>
...
int main(void)
{struct Info *i1;struct Info *i2;i1 = (struct Info *)malloc(sizeof(struct Info));i2 = (struct Info *)malloc(sizeof(struct Info));if (i1 == NULL || i2 == NULL){printf("内存分配失败!\n");exit(1);}printf("请录入第一个同学的信息...\n");getInput(i1);putchar('\n');printf("请录入第二个学生的信息...\n");getInput(i2);printf("\n录入完毕,现在开始打印...\n\n");printf("打印第一个学生的信息...\n");printInfo(i1);putchar('\n');printf("打印第二个学生的信息...\n");printInfo(i2);free(i1);free(i2);return 0;
}