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

目录
相关文章
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
35 3
|
17天前
|
存储 Java 程序员
结构体和类的内存管理方式在不同编程语言中的表现有何异同?
不同编程语言中结构体和类的内存管理方式既有相似之处,又有各自的特点。了解这些异同点有助于开发者在不同的编程语言中更有效地使用结构体和类来进行编程,合理地管理内存,提高程序的性能和可靠性。
24 3
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
68 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
19天前
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。
|
19天前
|
存储 缓存 算法
结构体和类在内存管理方面有哪些具体差异?
【10月更文挑战第30天】结构体和类在内存管理方面的差异决定了它们在不同的应用场景下各有优劣。在实际编程中,需要根据具体的需求和性能要求来合理选择使用结构体还是类。
|
28天前
|
C语言
【c语言】动态内存管理
本文介绍了C语言中的动态内存管理,包括其必要性及相关的四个函数:`malloc`、``calloc``、`realloc`和`free`。`malloc`用于申请内存,`calloc`申请并初始化内存,`realloc`调整内存大小,`free`释放内存。文章还列举了常见的动态内存管理错误,如空指针解引用、越界访问、错误释放等,并提供了示例代码帮助理解。
38 3
|
1月前
|
存储 C语言
C语言:一维数组的不初始化、部分初始化、完全初始化的不同点
C语言中一维数组的初始化有三种情况:不初始化时,数组元素的值是随机的;部分初始化时,未指定的元素会被自动赋值为0;完全初始化时,所有元素都被赋予了初始值。
|
1月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
56 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
1月前
|
编译器 程序员 C语言
深入C语言:动态内存管理魔法
深入C语言:动态内存管理魔法
|
30天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
25 0