结构体和指针

发布 2019-07-19 13:26:15 阅读 4961

一、 结构体。

结构体声明:结构体声明包含结构体关键字、类型名和数据成员。

例:struct student

char name;

char addr;

char age;

float height;

int weight;

char grade[7];

结构体变量:定义包含直接声明时定义、单独定义。

例:struct student

char name;

char addr;

char age;

float height;

int weight;

char grade[7];

xiaonei;//直接定义一个结构体变量时可以省略结构体类型名。

struct student xiaonei;

此外还可以利用宏定义来声明一个结构体变量。

例:typedef struct student

char name;

char addr;

char age;

float height;

int weight;

char grade[7];

structstudent;

结构体变量所占内存空间大小,可以参考其他相关文档。

成员的内存分配规律是这样的:从结构体的首地址开始向后依次为每个成员寻找第一个满足条件的首地址x,该条件是x % n = 0,并且整个结构的长度必须为各个成员所使用的对齐参数中最大的那个值的最小整数倍,不够就补空字节。

结构体中所有成员的对齐参数n的最大值称为结构体的对齐参数。

对齐规则。每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。

对齐步骤:1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

3、结合颗推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

备注:数组成员按长度按数组类型长度计算,如char t[9],在第1步中数据自身长度按1算,累加结构体时长度为9;第2步中,找最大数据长度时,如果结构体t有复杂类型成员a的,该a成员的长度为该复杂类型成员a的最大成员长度。

其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则: 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 2) 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节; 3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

当结构体中嵌套了结构体时,结构体内存空间对齐规则把嵌套结构体不当成整体来看,还是按其内部最宽基本类型数据成员的大小来对齐。

二、 指针。

定义一个指针变量:数据类型 *指针名;

例:char *p;

如上定义了一个指针变量p;其中p表示指针,存储的是变量的地址;*表示取指针p的内容,即指针内地址所指向的存储单元的内容。

指针变量所占内存:

sizeof(*p)= sizeof(datatype)=1;

sizeof(p)=sizeof(datatype *)3;//在8位机中指针占3个存储单元,在32位机中其占4个存储单元。

给一个指针变量赋值:

例:char a;

char *t;

char b[8];

p=&a;p=a;

p=t;p=b;

以上是给指针变量赋值的常用方法,给指针赋值后就可以称指针指向相应的变量或地址。

函数指针。当然一个函数指针也是一样,函数指针变量定义的特点是指针变量和*要合并在一个括号,这个括号前是函数返回值,后面是参数定义(一定是带一对括号)

char (*func1)(int ,char *)表示func1是一个函数指针,指向的函数定义 char func(int ,char *)这样 sizeof(func1)= 4;

函数指针定义这样写主要为不和返回值为指针的函数声明冲突。上述定义没有括号含义就变了,表示声明一个返回值为char *的函数func1

char * func1(int ,char *)

当然,如果你强行对这个func1取sizeof(),它的值也是 4,因为函数名相当于一个地址常量。

数组指针。指向一个数组的指针的格式与函数指针定义很相似,数组指针名和*要合在一个括号里,括号前是数组类型。括号后是用表示数组维数。

char (*p)[10]; 表示是指向一个一维字符数组的指针,这个数组的维数是10,所以sizeof仍然是4,因为它仍然是一个指针变量。(sizeof(p)=4)

用括号也是为了防止数组指针定义与指针数组的定义冲突。象把上述定义的括号去掉,含义完全变了。表示一个一维数组,数组项是char *,维数是 10,char * p[10];

这个按照数组的计算法则,sizeof(p)= sizeof(char *)10=40;

指针和数组的混合使用:

例:char *pv;

char array[10];

pv = array;

(pv+i) =pv[i]=array[i];

pv+i = array[i];

数组名就是其第一个元素的地址即数组首地址,当用数组名给指针赋值以后,数组名和指针在取地址和取数据元素的用法上是可以通用的,然而在计算内存空间大小时指针名和数组名是有区别的sizeof(数组名)表示计算数组所占内存空间大小,sizeof(指针名)表示计算指针所占内存空间大小(8位机其为3,32位机其为4)

第十三讲指向结构体的指针与链表 C语言

本讲首先介绍了c语言中指向结构体变量和结构体数组的指针变量的使用,接着介绍了结构体数据作为函数参数的使用,最后介绍了链表的概念和基本操作。要求大家掌握指向结构体变量的指针变量和指向结构体数组及数组元素的指针变量的定义和引用,理解指向结构体变量的指针变量 结构体变量及其成员作为函数参数的使用方法,掌握...

extern声明外部结构体

在extern声明外部结构体变量时,遇到问题如下 文件。struct struct plc mdl productinfo versiondate路由模块版本日期。uint16 versionid路由模块版本号。uint8 comtype路由模块通信方式。uint8 ch num路由模块信道个数。u...

数据结构,二维指针和数组 还有数据结构

自己建立头文件格式 include 指针 指针变量 是用来存放变量的存储地址的。p null int a 3 例如 p a 结论 p a p 3 指针变量定义的格式 类型名 指针名。最好采用int p 取值符号 后面加 地址 表示取这个地址里的值。地址符号 后面加 变量 表示取这个变量的地址。voi...

c指针详解 1

9.1指针是什么 9.1.1 指针是一类数据类型的统称 对于c语言来说,计算机的内存由连续的字节 byte 构成。这些连续的字节同样被连续地编上了号码以相互区别,这个号码就是所谓的地址 address 如图9 1所示。图9 1 内存单元与地址。指针 pointer 是c语言中的一类数据类型的统称。这...

谈CC 指针精髓

指针是c和c 语言编程中最重要的概念之一,也是最容易产生困惑并导致程序出错的问题之一。利用指针编程可以表示各种数据结构,通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯 并能像汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了 和c 语言的功能。在本文中...

开关结构和工作原理

开关由主体和智能控制器两部分组成 主体采用电磁系统作为操作机构,驱动触头运动以实现对主电路的接通或分断 智能控制器采用电力电子技术控制开关的运动特性,采用脉冲消磁技术提高开关的分闸速度。智能控制器对主电路电流和线圈供电电压进行检测,根据主电路电流变化情况进行故障诊断,推算绕组温升,一旦发生故障,发出...

钳形表的结构和原理

钳形表实质上是由一只电流互感器 钳形扳手和一只整流式磁电系有反作用力仪表所组成。钳型表的工作原理和变压器一样。初级线圈就是穿过钳型铁芯的导线,相当于1匝的变压器的一次线圈,这是一个升压变压器。二次线圈和测量用的电流表构成二次回路。当导线有交流电流通过时,就是这一匝线圈产生了交变磁场,在二次回路中产生...

水表的结构和工作原理

旋翼式水表是速度式水表的一种,是世界上用得最多的水表品种。在国家标准中,速度式水表的定义为 安装在封闭管道中,由一个动力元件组成,并由水流速直接使其获得运动的一种水表 当水流通过水表时,驱动叶轮 旋翼或螺翼 旋转,而水流的流速与叶轮的转速成正比,因水流驱动叶轮处喷口的截面积为常数,故叶轮的转速与流量...