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. [C#] 解决Silverlight反射安全关键(SecuritySafeCritical)时报“System.MethodAccessException: 安全透明方法 XXX 无法使用反射访问”的问题

    作者: zyl910 一.缘由 在Silverlight中使用反射动态访问时,经常遇到"System.MethodAccessException: 安全透明方法 XXX 无法使用反射访问-- ...

  2. IIS 重写 HTTP 重定向到 HTTPS

    1.购买SSL证书 2.IIS7 / IIS 7.5 下绑定 HTTPS 网站(购买Wildcard SSL泛域名证书可绑定多个子域名)参考上文 3.下载安装URL重写模块:Microsoft URL ...

  3. .NET 同步与异步 之 EventWaitHandle(Event通知) (十三)

    本随笔续接:.NET 同步与异步 之 Mutex (十二) 在前一篇我们已经提到过Mutex和本篇的主角们直接或间接继承自 WaitHandle: Mutex类,这个我们在上一篇已经讲过. Event ...

  4. Docker入门 - 002 Docker 的简单操作

    系统要求:CentOS 7.2 64 位操作系统. Docker 的简单操作 下载镜像 下载一个官方的 CentOS 镜像到本地 docker pull centos 下载好的镜像就会出现在镜像列表里 ...

  5. H+ 添加(新增)Tab选项卡

    //注:在contabs.js文件中 $(function () { }); 方法外 加入//注: data-name="' + menuName + '" 这句是加入的自定义属性 ...

  6. 使用PIP扩展BTARN

    下载安装部署 从GS1 US RosettaNet下载相应的PIP文件  新建BizTalk解决方案并设置签名 添加->现有项(C:\Program Files (x86)\Microsoft ...

  7. C++学习的书籍

    https://www.ossblog.org/master-c-programming-with-open-source-books/

  8. mysql知识汇总

    一.数据类型介绍 数据类型 字节长度 范围或用法 bigint 8 无符号[0,2^64-1],有符号[-2^63 ,2^63 -1] binary(M) M 类似Char的二进制存储,只包含byte ...

  9. Windows 10 Manager v2.3.3

    Windows 10 Manager 是专门用于微软 Windows10 的集所有功能于一身的实用工具,它包括了40多个不同的实用程序来优化.调整.清理.加快和修复您的 Windows 10,可以让你 ...

  10. SAP Parallel Accounting(平行分类账)业务配置及操作手册

    目录 SAP Parallel Accounting(平行分类账业务)配置及操作手册 SAP Parallel Accounting(平行分类账业务)配置及操作手册 Overview 业务说明 为了适 ...