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指针小记(十五)-结构和联合的更多相关文章

  1. C和C指针小记(十八)-使用结构和指针-双向链表

    1.双链表 1.1 双向链表的声明 在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针. 声明 typedef struct NODE { struct NODE * ...

  2. C和指针 第十五章 文件I/O

    stdio.h中包含了声明FILE结构 struct _iobuf { char *_ptr; //文件输入的下一个位置 int _cnt; //当前缓冲区的相对位置 char *_base; //指 ...

  3. C和C指针小记(十六)-动态内存分配

    动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...

  4. C和C指针小记(十七)-使用结构和指针-链表

    1.链表 链表(linked list)即使是一些包含数据的独立数据结构的(Node)集合. 链表中的每个节点通过链或指针链接在一起. 程序通过指针访问链表中的节点. 节点通常是动态分配的,但也有由节 ...

  5. C和指针 第十五章 习题

    15.8 十六进制倾印码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...

  6. C和指针 第十五章 二进制I/O

    二进制I/O 数据写入到文件效率最高的是用二进制形式写入,二进制输出避免了在数值转换为字符串过程中,所涉及的开销和精度损失,但而精致并非人眼所能阅读,所以这个技巧只有当数据被另一个程序按顺序读取才能使 ...

  7. C和C指针小记(十四)-字符串、字符和字节

    1.字符串 C语言没有字符串数据类型,因为字符串以字符串常量的形式出现或存储于字符数组中. 字符串常量和适用于那些程序不会对他们进行修改的字符串. 所有其他字符串都必须存储于字符串数组或动态分配的内存 ...

  8. C和C指针小记(十)-函数

    1.函数的定义 函数的定义就是函数体的实现. 语法: 类型 函数名(形式参数) 代码块 函数返回类型和函数名分开写是代码风格的问题,现代语言如swift返回值在函数名和参数表的后面,这样使得某些工程工 ...

  9. C和指针 第十五章 输入输出缓冲

    对于C,所有的I/O操作都只是简单的从程序移进或移出字节,这种字节流便成为流(stream),我们需要关心的只是创建正确的输出字节数据,以及正确的输入读取数据,特定的I/O设备细节都是对程序隐藏的. ...

随机推荐

  1. 生产系统ELK日志采集系统

    总结下,生产在运转的日志采集系统!后续的扩展在于elasticsearch节点与logstash节点与kafka+zookeeper,目的提高吞吐量!

  2. 解决windows 下 mysql命令行导入备份文件 查询时乱码的问题

    Mysql导入乱码,一般在命令行会遇到.下面说的是命令行的情况下解决乱码问题: 方法一: 通过增加参数 –default-character-set = utf8 解决乱码问题 mysql -uroo ...

  3. ElasticSearch 5.0及head插件安装

    一.elasticsearch安装配置 1.官网下载源码包 https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.0 ...

  4. Mybatis判断map参数是否存在

    <select id="selectByCondition" parameterType="java.util.HashMap" resultMap=&q ...

  5. 深入理解JDBC的超时设置

    恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数据库的各种超时设置及其设置方法做介绍. 真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到DDos攻击后,整个服务都垮掉了.由于第四 ...

  6. cx_oracle访问处理oracle中文乱码问题

    cx_oracle访问处理oracle中文乱码问题 问题描述 使用docker打包了centos镜像,编码为gbk,随后访问oracle出现了很多乱码.其原因自然是因为编码不一致,服务器为zhs16g ...

  7. Nmap备忘单

    #在推特上看到,感觉做的相当不错就转一波. 目标规格 开关 例 描述   nmap 192.168.1.1 扫描一个IP   nmap 192.168.1.1 192.168.2.1 扫描特定的IP地 ...

  8. Shell 实现多线程(多任务)

    实现方案: 1.命令结尾添加:& #/bin/bash all_num= a=$(date +%H%M%S) ${all_num}` do { echo ${num} } & done ...

  9. 此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet。

    1.问题描述 mvc从一个路径获取所有的图片信息,ajax方法如下: function getimages(day) { var year = $("#selYear").val( ...

  10. Halcon中模板匹配方法的总结归纳

    基于组件的模板匹配: 应用场合:组件匹配是形状匹配的扩展,但不支持大小缩放匹配,一般用于多个对象(工件)定位的场合. 算法步骤: 1.获取组件模型里的初始控件 gen_initial_componen ...