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设备细节都是对程序隐藏的. ...
随机推荐
- __NSArrayI __NSArray0 __NSSingleObjectArrayI __NSPlaceholderArray __NSArrayM
如果你的 全局 可变数组 前面 用了 copy修饰,那么 调用 arr addObjectsFromArray: 的时候 就 会崩溃,而且提示你 是 [__NSArray0 addObje ...
- 分析轮子(二)- << ,>>,>> (左移、右移、无符号右移)
前言:写 分析轮子(一)-ArrayList.java 的时候看到源码中有 int newCapacity = oldCapacity + (oldCapacity >> 1); 这样的代 ...
- atitit 各分公司ceo cao行政经理职责.docx
1.1. 人员招募--分公司高层人员招募(每月招募四五人吧,每周一人平均) 1 1.2. 组织架构优化 1 1.3. 制度建设 健全并完善分公司内部管理机构设置,优化分公司业务管理流程: 1 1.4 ...
- 【iCore1S 双核心板_ARM】例程十八:SD_IAP_FPGA实验——更新升级FPGA
实验现象及操作说明: 1.烧写程序成功,绿色ARM·LED灯点亮,三色FPGA·LED灯循环点亮,烧写失败,如果挂载SD卡失败,红灯快闪,如果打开文件失败,蓝灯快闪,读取文件指针移动失败,白灯点亮,升 ...
- [Java并发编程(二)] 线程池 FixedThreadPool、CachedThreadPool、ForkJoinPool?为后台任务选择合适的 Java executors
[Java并发编程(二)] 线程池 FixedThreadPool.CachedThreadPool.ForkJoinPool?为后台任务选择合适的 Java executors ... 摘要 Jav ...
- count(*)、count(1)和count(列名)的区别
count(*).count(1)和count(列名)的区别 1.执行效果上: l count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL l count(1)包 ...
- Android跳转到应用商店的APP详情页面,以及 Google GMS 各个apk的包
转自:http://www.jianshu.com/p/a4a806567368 需求: 从App内部点击按钮或链接,跳转到应用商店的某个APP的详情页面.让用户 下载 或 评论. 实现: /** * ...
- 【OCP、OCM、高可用等】小麦苗课堂网络班招生简章(从入门到专家)--课程大纲
[OCP.OCM.高可用等]小麦苗课堂网络班招生简章(从入门到专家)--课程大纲 小麦苗信息 我的个人信息 网名:小麦苗 QQ:646634621 QQ群:618766405 我的博客:http:// ...
- Matrix 高斯消元Gaussian elimination 中的complete pivoting和partial pivoting
首先科普下Pivoting的含义 一般翻译为“主元”,在对矩阵做某种算法时,首先进行的部分元素.在线性规划的单纯形法中常见.wiki的解释如下:Pivot element(the first elem ...
- php四个常用类封装
这4个类分别是Mysql类. 分页类.缩略图类.上传类. Mysql类 <?php /** * Mysql类 */ class Mysql{ private static $link = nul ...