C和指针 第十章 结构和联合 (一)
结构体:
聚合数据类型是指,能够同时存储超过一个的单独数据,C语言中有两个聚合数据类型,数组和结构体。数组中储存的类型必须相同,元素通过下标和指针引用来访问的。
结构体也是一些值的集合,但是结构体中每个元素的值的类型可以不同,每个元素都有自己的名字,和整数字符一样,结构体也是标量类型
结构体声明:
- struct tag { memeber-list } variable-list;
结构体声明要包含所有的成员的类型和名字
- struct tag {
- char *name;
- int *age;
- } people;
其中,tag时标签字段,可以在后续的声明中使用tag代表成员列表:
- struct tag animal;
此处的声明和上面的people一样,animal和people对于编译器来说,是两个不同的类型的。
如果需要定义相同的类型,可以通过typedef来创建新类型:
- typedef struct {
- char *name;
- int *age;
- } animal;
现在animal是一新的结构体类型,可以直接使用他进行赋值
- animal dog;
结构体的成员:
结构体的成员可以时标量,指针,和其他结构体等等,但是不可以是自身类型的成员,即自己。结构体成员可以通过点号访问
- #include <stdio.h>
- typedef struct {
- char *name;
- int age;
- } animal;
- int main()
- {
- animal dog = { "ted", 3};
- printf("%s", dog.name);
- return 0;
- }
运行结果:
如果是指向结构体的指针,可以先解引用操作,然后在使用点操作符,C有个快捷的方法,使用 -> 访问结构体指针指向的结构体成员,上面代码可以如下改写:
- animal dog = { "ted", 3};
- animal *ptr = &dog;
- printf("%s", ptr -> name);
结构体时不可以包含自身类型的成员的,不过可以包含指向自己类型的指针的。
- #include <stdio.h>
- struct SELF {
- char *name;
//selfPtr是指向自身类型的指针- struct SELF * selfPtr;
- } animal;
- int main()
- {
- struct SELF dog = { "ted", NULL};
- struct SELF cat = {"mimi", &dog};
- printf("%s", cat.selfPtr -> name);
- return 0;
- }
运行结果:
注意:下面的这种声明是非法的,因为类型名直到声明结束才定义
- typedef struct {
- char *name;
- struct SELF * selfPtr;
- } SELF;
解决方法是添加一个结构标签。
- typedef struct SELF {
- char *name;
- struct SELF * selfPtr;
- } animal;
如果两个结构体相互依赖引用,一个结构体包含另一个结构体,另一个结构体包含这个结构体。那么可以使用不完整声明,先声明一个结构体作为标识符,然后使用他,然后把成员和标识符关联。
- //声明表示符,在A中使用
- struct B;
- struct A {
- struct B *bPtr;
- };
- //关联成员
- struct B {
- struct A *aPtr;
- };
结构体的初始化,类似数组,大括号内部包含逗号分割的初始值,如果初始值列表不够用,剩余的结构成员将使用缺省值初始化。
- struct {
- char *name;
- int age;
- } me = {"yangxunwu", 24};
结构体的储存分配:
由于结构体类别的成员的类型可以不一样,编译器在给成员列表分配内存时,一个接着一个的分配,只有当储存成员需要满足边界对齐时,成员之间会出现储存间隙。系统禁止在一个结构的起始位置跳过几个字节来满足边界对齐要求,因此所有的结构的起始储存位置,必须是边界要求最严格的数据类型所要求的位置,如下:
- #include <stdio.h>
- int main()
- {
- struct {
- char ch1;
- int age;
- char ch2;
- } stc1;
- struct {
- int age;
char ch1;
char ch2;- } stc2;
- printf("%lu %lu", sizeof(stc1), sizeof(stc2));
- return 0;
- }
可以通过重新排序成员,让边界对齐要求高的先出现,如上运行:
int类型占四个字节,char占一个字节,因为要从起始位置对齐,所以stc1的第一个char占4字节,而stc2中,age占四个字节,ch1和ch2在一起占四个字节。sizeof可以返回一个long unsigned int表示整个结构体长度。
- stddef.h宏 offsetof(type, member) 返回指定成员,距离结构开始偏移几个字节。
- #include <stdio.h>
- #include <stddef.h>
- int main()
- {
- struct stc1 {
- char ch1;
- int age;
- char ch2;
- } ;
- struct stc2 {
- int age;
- char ch1;
- char ch2;
- } ;
- printf("%lu %lu", offsetof(struct stc1, ch2), offsetof(struct stc2, ch2));
- return 0;
- }
运行:
C和指针 第十章 结构和联合 (一)的更多相关文章
- C和指针 第十章 结构和联合 (二)
结构体传值: 结构体也是标量,像字符和整数一样,可以传递给一个函数,但是传入整个结构体效率很低,可以传入指向结构体的指针来提高效率.如果不希望程序对结构体变量改变可以加入const关键词. typed ...
- C和指针 第十章 结构和联合 习题
1. 记账信息结构联合 typedef struct { unsigned int areaNum; unsigned int transNum; unsigned int station; } ph ...
- C的指针疑惑:C和指针10(结构和联合)
结构也可以作为传递给函数的参数,它们也可以作为返回值从函数返回,相同类型的结构体变量相互之间可以赋值. 申明结构时使用另一种良好技巧是用typedef创建一种新的类型. typedef struct{ ...
- C和C指针小记(十五)-结构和联合
1.结构 1.1 结构声明 在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称. struct tag {member-list} variable-list; 例如 //A s ...
- C语言的结构和联合,以及PHP是怎么实现弱类型的
C语言的结构(struct):包含多个成员,可能有多种数据类型,并且需要分配几种类型占用空间之和的空间. 联合(union):支持多种类型,供使用者使用其中一种数据类型,当然是需要分配其中占用空间最大 ...
- 【转】结构struct 联合Union和枚举Enum的细节讨论
结构struct 联合Union和枚举Enum的细节讨论 联合(Union)是一种构造数据类型,它提供了一种使不同类型数据类型成员之间共享存储空间的方法,同时可以实现不同类型数据成员之间的自动类型转换 ...
- C++笔记--指针数组和结构
指针 类型为T*的变量能保存一个类型T对象的地址 Char c=‘a’:Char * p=& c://保存了c的地址 指针的操作一般都是间接的引用,就是相当于引用指针所指的对象. 0是一个特殊 ...
- C语言入门第十章----结构体
C语言结构体从本质上讲是一种自定义的数据类型,只不过这种数据类型比较复杂,是由int.char .float等基本类型组成的,你可以认为结构体是一种聚合类型. 在实际开发中,我们可以将一组类型不同的. ...
- C和指针 (pointers on C)——第十章:结构和联合(下一个)锻炼
//1.本章只为了刷存在演习.. . typedef struct phone { char * quhao; char * jiaohuantai; char * zhanhaoma; }; typ ...
随机推荐
- struts2中的OGNL详解
先了解一下OGNL的概念 OGNL的全名称Object Graph Navigation Language.全称为对象图导航语言,是一种表达式语言.使用这种表达式语言,你可以通过某种表达式语法,存取J ...
- 在运行Hibernate Hello World程序的时候,抛如下错误: view plain Exception in thread "main" org.hibernate.exception.LockAcquisitionException 解决方法
在运行Hibernate Hello World程序的时候,抛如下错误: Exception in thread "main" org.hibernate.exception.Lo ...
- Struts2文件上传和文件下载
一.单个文件上传 文件上传需要两个jar包: 首先制作一个简单的页面,用于实现文件上传 <h1>单个文件上传</h1> <s:form action="uplo ...
- Java设计模式之单例
一.Java中的单例: 特点: ① 单例类只有一个实例 ② 单例类必须自己创建自己唯一实例 ③ 单例类必须给所有其他对象提供这一实例 二.两种模式: ①懒汉式单例<线程不安全> 在类加载时 ...
- ES5/标准 ECMAScript 内置对象
https://www.w3.org/html/ig/zh/wiki/ES5/%E6%A0%87%E5%87%86_ECMAScript_%E5%86%85%E7%BD%AE%E5%AF%B9%E8% ...
- codevs 2495 水叮当的舞步
题目链接:水叮当的舞步 我现在开始发题目链接了(主要还是因为懒得整理题面)-- 这道题一开始是看到MashiroSky在写,于是我也开始写这道题了(说白了就是狙击他)-- 这道题看到这么小的范围当然给 ...
- tfs2012迁移,只用到源代码管理
背景:在虚拟机里面安装的tfs,后来发觉C盘空间太少了,运行卡,准备重新配置一台虚拟机当做tfs服务器.安装相同版本的tfs.数据库(至少比原来的版本一样或者更高版本,要不附加不了数据库). 1.确保 ...
- oschina(开源中国)的Git代码托管平台使用教程
oschina(开源中国)的Git代码托管平台使用教程 第一章 平台介绍 一. Git@OSC简介 开源中国的Git@OSC一个账号最多可以创建1000个项目,包含公有和私有,开源中国代码托管地址:h ...
- 第一个Android应用--签证无忧 上线
用了大概1个多星期的时间,把一个简单的应用完成,[签证无忧]是基于在我所在公司办理签证的前提下,为方便客户查询进度所开发,后来我加了淘宝的购买链接,这样客人在以后需要时不需要到淘宝查找了. 签证无忧这 ...
- 代码生成工具——Entity Framework Power Tools
Entity Framework Power Tools是VS上的一个根据数据库生成Model的Code First映射工具.在VS里面右键即可看到.什么,没有? 别慌,可以单独下载的,见 https ...