C和C指针小记(十五)-结构和联合
1、结构
1.1 结构声明
在声明结构时,必须列出它包含的所有成员.这个列表包括每个成员的类型和名称.
struct tag {member-list} variable-list;
例如
//A
struct {
int a;
char b;
float c;
} x;
//B
struct {
int a;
char b;
float c;
} y[20], *z;
注意:这两个声明会被编译器当作两种截然不同的类型,即使他们的成员列表完全相同.
下面这跳语句是非法的
z = &x;
可以利用tag(标签)字段来给结构的成员列表提供一个名字. 标签允许多个声明使用同一个成员列表,并创建同一种类型的结构.
//标签 SIMPLE 和这个成员列表联系在一起了. 但它没有创建任何变量. 标签不是结构的名字,更不能用来定义结构
struct SIMPLE {
int a;
char b;
float c;
};
//根据标签声明结构
struct SIMPLE x;
struct SIMPLE y[20], *z;
z = &x;//x ,y ,z 都是同一种类型的结构变量
一种更好的定义结的方法:
typedef struct {
int a;
char b;
float c;
} Simple;
Simple x;
Simple y[20], *z;
现在 Simple 是结构的名称了,而不是成员列表的标签.
1.2 结构成员
结构成员可以是标量,数组,指针甚至是其他结构
struct COMPLEX {
float f;
int a[10];
long *lp;
struct SIMPLE s;
struct SIMPLE sa[10];
struct SIMPLE *sp;
};
一个结构的成员的名字可以和其他结构的成员的名字相同,所以这个结构的成员a 并不会与 struct SIMPLE s; 的成员a冲突.
1.3 结构体成员的访问
直接访问
如果有一个结构体
struct COMPLEX comp;
可以用 . 访问结构调整的成员
comp.s
comp.s.a 或者 (comp.s).a
( (comp.sa)[4] ).c 或者 comp.sa[4].c
点操作符的结合是从左到右的
间接访问
如果拥有一个指向结构的指针,这时要访问这个结构的成员.要首先对指针执行间接反问操作.
然后使用点操作符反问它的成员. 但是点操作符的优先级是高于间接访问操作符的.所以你必须在表达式中使用括号..
void func( struct COMPLEX *cp);
(*cp).f;
由于**点操作符的优先级是高于间接访问操作符 ** 使得间接访问必须加括号,这一点体验很不好.
好在C语言提供了更为方便的箭头操作符来完成间接访问 ->
例如上例
cp->f
cp->a
cp->s
但是使用箭头操作符访问成员时,左操作数必须是一个指向结构的指针
1.4 结构的自引用
//非法
struct SELF_REF1 {
int a;
struct SELF_REF1 b;
int c;
};
//合法
struct SELF_REF2 {
int a;
struct SELF_REF2 *b;
int c;
};
结构自引用的形式必须是指针.编译器在结构的擦含高浓度确定之前就已经知道指针的长度,所以这种类型的自引用是合法的.
不用纠结,因为它事实上所指向的是同一种类型的不同结构. 链表和树都是用这种技巧实现的.
一个陷阱:
typedef struct {
int a;
SELF_REF3 *b;
int c;
} SELF_REF3;
这个声明的目的是为这个结构创建类型名 SELF_REF3, 但是这样会失败.因为类型名直到声明的末尾才定义,所以在结构声明的内部它尚未定义.
解决方案是定义一个结构标签来声明b,如下
typedef struct SELF_REF3_TAG {
int a;
struct SELF_REF3_TAG *b;
int c;
} SELF_REF3;
1.5 不完整的声明
如果必须声明一些相互之间存在依赖的结构,并且每个结构都引用来其他结构的标签,那么该首先声明那些结构呢?
这个时候就用到不完整声明了.
struct B;
struct A {
struct B *partner;
//...
};
struct B {
struct A *partner;
//...
};
1.6 结构的初始化
值放在花括号内部,由都好分割初始值列表.
struct INT_EX {
int a;
short b[10];
Simple c;
} x = {
10,
{1, 2, 3, 4, 5 },
{25, 'x', 1.9}
};
2 结构、指针和成员
直接通过指针访问结构和它们的成员的操作符是相当简单的.
C和C指针小记(十五)-结构和联合的更多相关文章
- C和C指针小记(十八)-使用结构和指针-双向链表
1.双链表 1.1 双向链表的声明 在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针. 声明 typedef struct NODE { struct NODE * ...
- C和指针 第十五章 文件I/O
stdio.h中包含了声明FILE结构 struct _iobuf { char *_ptr; //文件输入的下一个位置 int _cnt; //当前缓冲区的相对位置 char *_base; //指 ...
- C和C指针小记(十六)-动态内存分配
动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...
- C和C指针小记(十七)-使用结构和指针-链表
1.链表 链表(linked list)即使是一些包含数据的独立数据结构的(Node)集合. 链表中的每个节点通过链或指针链接在一起. 程序通过指针访问链表中的节点. 节点通常是动态分配的,但也有由节 ...
- C和指针 第十五章 习题
15.8 十六进制倾印码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...
- C和指针 第十五章 二进制I/O
二进制I/O 数据写入到文件效率最高的是用二进制形式写入,二进制输出避免了在数值转换为字符串过程中,所涉及的开销和精度损失,但而精致并非人眼所能阅读,所以这个技巧只有当数据被另一个程序按顺序读取才能使 ...
- C和C指针小记(十四)-字符串、字符和字节
1.字符串 C语言没有字符串数据类型,因为字符串以字符串常量的形式出现或存储于字符数组中. 字符串常量和适用于那些程序不会对他们进行修改的字符串. 所有其他字符串都必须存储于字符串数组或动态分配的内存 ...
- C和C指针小记(十)-函数
1.函数的定义 函数的定义就是函数体的实现. 语法: 类型 函数名(形式参数) 代码块 函数返回类型和函数名分开写是代码风格的问题,现代语言如swift返回值在函数名和参数表的后面,这样使得某些工程工 ...
- C和指针 第十五章 输入输出缓冲
对于C,所有的I/O操作都只是简单的从程序移进或移出字节,这种字节流便成为流(stream),我们需要关心的只是创建正确的输出字节数据,以及正确的输入读取数据,特定的I/O设备细节都是对程序隐藏的. ...
随机推荐
- 在GDAL中添加GDALRasterizeGeometriesBuf函数
缘起 GDAL的栅格化算法中有GDALRasterizeLayers.GDALRasterizeLayersBuf和GDALRasterizeGeometries函数,但是没有GDALRasteriz ...
- 【C#】C#线程_基元线程的同步构造
目录结构: contents structure [+] 简介 为什么需要使用线程同步 线程同步的缺点 基元线程同步 什么是基元线程 基元用户模式构造和内核模式构造的比较 用户模式构造 易变构造(Vo ...
- springboot 项目中读取资源文件内容 如图片、文档文件
1 问题描述:在 springboot 项目中有时候会需要读取一些资源文件,例如 office的 docx 文档或者 png.jpg的图片.在多模块项目中资源文件需要放到启动项目的 Resources ...
- BTARN 接收消息流以3A7为例
 1.RNIFReceive.aspx 页接收来自发起方的传入消息. (如果发起方是BizTalk则类似于:http://localhost/BTARNApp/RNIFSend.aspx?TPUrl ...
- go 资料
channel 底层原理 https://www.youtube.com/watch?v=KBZlN0izeiY go concurrency https://www.youtube.com/watc ...
- MySQL安装、配置、测试
MySQL安装.配置.测试(win7_64bit) 目录 1.概述 2.本文用到的工具 3.MySQL安装配置 4.Java访问MySQL测试 5.注事事项 6.相关博文 >>看不清的图片 ...
- 【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其一)
策划填Excel表时,约定对于复杂类型的数据采用Json的格式填写.如下图,D列的内容是Json数据. 单元格中的Json如下. { "name": "BeJson2&q ...
- 印象笔记中的美人鱼 mermaid
美人鱼 mermaid 是印象笔记中Markdown模式下新增的一种代码模式,它能支持更多的高级图表功能,如流程图.甘特图.时序图. 我最喜欢的应该是甘特图,最惊喜的是流程图. 当然,印象笔记还支持其 ...
- 数据仓库:Mysql大量数据快速导出
背景 写这篇文章主要是介绍一下我做数据仓库ETL同步的过程中遇到的一些有意思的内容和提升程序运行效率的过程. 关系型数据库: 项目初期:游戏的运营数据比较轻量,相关的运营数据是通过Java后台程序聚合 ...
- HTTP 03 HTTP 报文
客户端的HTTP报文, 叫做请求报文 服务器端的叫做 响应报文. HTTP 报文本身是由多行 (用 CR+LF 作换行符) 数据构成的字符串文本. HTTP 报文大致分为报文首部 和 报文主体 两部分 ...