自学内容网 自学内容网

【C】Structure

在这里插入图片描述

参考摘抄学习来自:

1 定义

它允许您存储不同类型的数据项。

结构体中的数据成员可以是基本数据类型(如 int、float、char 等),也可以是其他结构体类型、指针类型等。

struct tag { 
    member-list
    member-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;
}

原文地址:https://blog.csdn.net/bryant_meng/article/details/140202728

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!