C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一

简介: C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一

简单介绍

结构体是一些值的集合,结构的每个成员可以是不同的类型。

例如描述书是比较复杂的,包括书名、作者、出版社、定价、书号等。

我们可以创建一个书的类型,用来描述书,存储书的各项数据。将这若干项数据集合起来就是一个结构体


声明与定义

声明后定义

注:在声明结构体类型时,最后的分号不能漏掉

声明时定义

特殊的声明

不完全声明

对匿名结构体类型进行探讨:

struct//匿名结构体类型
{
    char c;
    int i;
    char ch;
    double d;
}n;
struct
{
    char c;
    int i;
    char ch;
    double d;
}*p;
int main()
{
    p = &n; //error
    return 0;
}

以上两个匿名结构体类型虽然里面的成员是完全相同的,但是编译器会把上面的两个声明当成完全不同的两个类型。所以是非法的。


注:匿名结构体只能使用一次,不能再用于创建结构体变量。


结构自引用

创建一个情景:我们创建一个存储图书馆各项数据的结构体类型,其中包括图书、内饰等等。而图书中又存储着有关图书的各项数据,这时就可以用到结构的自引用了。例如:

struct book //图书
{
    char type[10];
    char name[20];
    int price;
    char number[30];
};
struct upholstery //内饰
{
    char WallColor[10];
    char CeilingMolding[30];
    int LampSwitch;
};
struct library
{
    struct book b;
    struct upholstery u;
    double d;
};

对结构自引用进行探讨

struct Node
{
    int n;
    struct Node n;
};

当我们用struct Node来创建变量时,会发现这个变量的大小是无法计算的,进入了一个死递归的状态。

因此,这种写法是非法的。

正确的写法

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

正确的写法

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

不可以包含同类型的变量,可以包含同类型的指针变量。

与链表有关,在数据结构中会学到。链表的结点包罗两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

另一种错误写法,将匿名结构体与自引用结合起来

struct
{
    int n;
    struct* next;
 
};

很显然,这种写法是非法的。那么此时想尝试用typedef修改一下,可不可行呢?

typedef struct
{
    int n;
    Node* next;
 
}Node;

来将这段代码捋一捋:将匿名结构体自定义为Node,那么先要让匿名结构体定义。而匿名结构体定义时要建立指针变量Node* next之后才算完成;但此时自定义还没有把struct定义为Node,故而以Node为类型的next变量不能成功建立。从而我们得知这段代码也是错误的,正确写法应该先自定义完成再定义结构体:

typedef struct Node
{
    int n;
    Node* next;
 
}Node;

结构体的初始化

struct A
{
    int i;
    char c;
}a;
struct B
{
    int n;
    char e;
    struct A a;
}b;
int main()
{
    struct A a = { 32,'a' };//直接初始化
    printf("%d\n%c\n", a.i, a.c);
    b.n = 64;
    b.e = 'b';
    //利用操作符“.”初始化
    b.a.i = 128;
    b.a.c = 'c';
    //结构自引用(结构嵌套)的初始化
    printf("%d  %c  %d  %c", b.n, b.e, b.a.i,b.a.c);
    return 0;
}


利用操作符“->”进行初始化

struct book
{
    int price;
    char name[20];
}b1,*p;
int main()
{
    p = &b1;
    p->price = 64;
    printf("%d\n", p->price);
    return 0;
}



C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二:https://developer.aliyun.com/article/1530420

目录
相关文章
|
19天前
|
网络协议 编译器 Linux
结构体(C语言)
结构体(C语言)
|
7天前
|
存储 编译器 定位技术
结构体数组在C语言中的应用与优化策略
结构体数组在C语言中的应用与优化策略
|
13天前
|
存储 编译器 数据库
结构体数组在C语言中的应用与优化技巧
结构体数组在C语言中的应用与优化技巧
|
17天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
20 0
|
18天前
|
程序员 C语言
C语言内存管理:malloc、calloc、realloc与free函数详解
C语言内存管理:malloc、calloc、realloc与free函数详解
14 0
|
18天前
|
存储 编译器 C语言
C语言的联合体:一种节省内存的数据结构
C语言的联合体:一种节省内存的数据结构
18 0
|
18天前
|
C语言
C语言中的结构体
C语言中的结构体
8 0
|
20天前
|
编译器 C语言 C++
【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?
【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?
10 0
|
20天前
|
存储 C语言
【C语言进阶篇】整数在内存的存储——原码、反码、补码
【C语言进阶篇】整数在内存的存储——原码、反码、补码
|
20天前
|
程序员 编译器 C语言
【c语言】详解动态内存管理
【c语言】详解动态内存管理
13 0