C和指针 (pointers on C)——第十章:结构体和联合(上)

第十章 结构和联合

这个部分先介绍了.运算符,可以供直接访问,还介绍了->运算符,它代替结构体指针的间接访问操作(*struct).xxx

这一章新手理解起来不算太难,没有学过操作系统的话理解位段、对齐等概念会有一些问题。

越发的说明了指针和内存绝对是C的核心。

总结:

结构声明列出了结构包含的成员列表,不同类型的值可以存储在一起。

不同的结构声明即使他们的成员列表相同也被认为是不同的类型。

声明结构时使用typedef创建一种新类型是一个好方法。

typedef struct

{

int a;

char b;

float c;

}simple;

跟结构标签的结果几乎相同。区别在于simple现在是一个类型名而不是结构体,以后声明就是下面这个样子。

simple x;

simple y[20], *z;

结构不能包含类型也是这个结构的成员,否则在分配地址的时候,会出现无穷大。但是可以包含一个指向这个结构的指针。

这个常常用在链式结构中。为了声明两个结构,每个结构都包含一个指向对方的指针的成员。

初始化的时候可以由一个花括号包围的值列表进行初始化。

编译器为一个结构变量的成员分配内存时要满足它们的边界对齐要求。在实现结构存储的边界对齐时,可能会浪费部分空间。根据边界对齐要求降序排列结构成员可以最大限度地减少结构存储中浪费的内存空间。

如果想要减少对齐造成的损失,一般来说声明的过程中要降序排列。可以利用offstof宏(stddef.h)+sizeof来找个更好的办法。

结构可以作为形参传递给函数,也可以作为返回值返回但是绝对不提倡!!!严重浪费内存空间。

最好形参和返回值都用指针,如果怕修改结构本身,那么就加个const!

位段个人不是理解很深,理解来看是可以将长度为奇数的值包装在一起节省空间。

Union和struct是两个不同的故事。所有Union的成员都存储于同一个内存位置。也可以进行初始化,但是初始化必需与联合第一个成员类型匹配。

关于初始化:

union{

int a;

float b;

char c[4];

} x = {5};

这样就把x.a初始为5。

警告:

1、具有相同成员列表的结构声明产生不同类型。

这就像函数一样,跟声明关系很大。

2、使用typedef为一个自引用的结构定义名字时应该小心。

自引用一定要记住,要引用指针。

3、向函数传递结构参数是低效的。

要对内存的形参进行拷贝,这份拷贝放在内存里实在是太浪费空间。

编程提示:

1、typedef声明放在头文件中。到是用到就#include回来。

2、结构成员的最佳排列形式并不一定就是考虑边界对齐而浪费内存空间最少的那种排列方式。

很显然,为了对齐,有时候你不得不打乱声明的顺序,从而导致可读性的降低。

3、把位段成员显式得声明为signed int 或者 unsigned int类型。

4、位段是不可抑制的。

5、位段使源代码中位的表达式更加清楚。

问题:

1、成员和数组元素有什么区别?

成员可以具备不同的类型,数组不行。

2、结构名和数组名有什么不同?

数组名是一个指针常量。但是结构名就是个标签tag,跟class名类似,没有实例的话,是不会对其分配内存的。

3、结构的声明:

struct tag{member-list } variable-list;

tag、member-list、variable-list三者必需有二。

时间: 2024-10-10 02:07:41

C和指针 (pointers on C)——第十章:结构体和联合(上)的相关文章

C和指针 (pointers on C)——第十章:结构体和联合(下)习题

//1.这一章的习题纯粹为了刷存在感... typedef struct phone { char * quhao; char * jiaohuantai; char * zhanhaoma; }; typedef struct call { char * date; char * time; phone * shiyong; phone * self; phone * hujiao; }; 2. typedef struct cash { float retail_price; float a

12个C语言面试题,涉及指针、进程、运算、结构体、函数、内存,看看你能做出几个!

1.gets()函数 问:请找出下面代码里的问题: #include<stdio.h> int main(void) { char buff[10]; memset(buff,0,sizeof(buff)); gets(buff); printf("\n The buffer entered is [%s]\n",buff); return 0; } 答:上面代码里的问题在于函数gets()的使用,这个函数从stdin接收一个字符串而不检查它所复制的缓存的容积,这可能会导致

结构体指针

结构体与指针 1.结构体指针的数值为某个结构体的内存空间的地址,从而指针指向某个结构体. 2.结构体指针的初始值为空(0),不指向任何结构体. 3.malloc操作:创建一个新的内存空间(从内存中选择一个内存空间存储结构体),p指向这个结构体,p的值为这个结构体的内存空间的地址. 4.结构体指针的赋值:一个结构体指针的数值等于另外一个结构体指针的数值,从而两个结构体指针指向相同的结构体.当对某个结构体进行访问时,选择的结构体指针只要满足该结构体指针指向这个结构体即可,即可以有很多种选择. 5.当

黑马程序员 C语言-枚举,结构体,指针

一.枚举 ※枚举变量的定义 前面只是定义了枚举类型,接下来就可以利用定义好的枚举类型定义变量. 跟结构体一样,有3种方式定义枚举变量 1.先定义枚举类型,再定义枚举变量 enum Season {spring, summer, autumn, winter}; enum Season s; 2.定义枚举类型的同时定义枚举变量 enum Season {spring, summer, autumn, winter} s; 3.省略枚举名称,直接定义枚举变量 enum {spring, summer

入职培训笔记记录--day9(1、指针函数与函数指针、函数指针数组 2、malloc memset 3、递归函数 4、结构体 5、共用体---》大小端 6、枚举)

1.指针函数与函数指针.函数指针数组 指针函数:返回值为指针的函数 char *fun() { char str[] = "hello world"; return str; } int main() { char *p = fun(); puts(p); return 0; } 编译时,会出现警告,返回了一个已经被释放掉的内存空间的首地址解决方法:1.static 2.char *str = "hello world"; 3.malloc 注意:使用完后要free

c++指向结构体变量指针

转自http://www.jb51.net/article/42140.htm 定义: 结构体变量的指针就是该变来那个所占据的内存段的起始地址.可以设一个指针变量,来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址. 设p是指向结构体变量的数组,则可以通过以下的方式,调用指向的那个结构体中的成员: (1)结构体变量.成员名.如,stu.num. (2)(*p).成员名.如,(*p).num. (3)p->成员名.如,p->num. 代码如下: #include<iostrea

C语言开发函数库时利用不透明指针对外隐藏结构体细节

1 模块化设计要求库接口隐藏实现细节 作为一个函数库来说,尽力减少和其调用方的耦合,是最基本的设计标准.C语言,作为经典"程序=数据结构+算法"的践行者,在实现函数库的时候,必然存在大量的结构体定义,接口函数需要对这些结构体进行操作.同时,程序设计的模块化要求库接口尽量少的暴露其实现细节,接口参数尽量使用基本数据类型,尽量避免在形参中暴露库内结构体的定义. 2 隐藏结构体的两种方法 以笔者粗浅的认识,有两种最常用的方法,可以实现库内结构体定义的隐藏:接口函数形参使用结构体指针,接口函数

EDKII CR宏:根据成员指针获取父结构体变量指针

核心提示: 1. CR宏 (Containing Record):根据成员指针获取父结构体变量指针 2. 0 指针的妙用. 在EDKII 的代码中有不少关于CR宏的使用,如 时钟中断处理函数CoreTimerTick. VOID EFIAPI CoreTimerTick ( IN UINT64 Duration ) { IEVENT *Event; ... if (!IsListEmpty (&mEfiTimerList)) { Event = CR (mEfiTimerList.Forward

结构体指针概要

结构体指针 指针当做函数参数 数组当做函数参数 1.结构体指针 指向结构体变量的指针.称为结构体指针 Student stu ={0}; Student *p = &stu; Student  * 结构体指针类型(类型), p结构体指针变量(变量名); &stu 结构体变量地址(初值) (*p).sex = 'm'; p->sex= 'm'; (*p)对指针取值后是结构体变量,.sex是访问成员变量 使用指针可以指向操作符直接访问结构体成员p->sex 1.结构体指针 结构体指