Mohican_4/22 结构体 typedef 枚举 联合 位段 内存对齐

一.结构体

struct  Test
{
	int a;
	int b;
	int c;
};

关键字 struct  ,表示其是一个结构体,后面是一个可选的标记(Test)

strcut Test Code

strcut Test 的作用类似于 int 或float的 声明。

a.在定义之后跟变量名,声明结构的过程和定义结构变量的过程可以使用合并成一步

struct  Test
{
	int a;
	int b;
	int c;
}Code;

b.不使用标记Tag, 直接写变量名

struct  
{
	int a;
	int b;
	int c;
}Code;
如果想多次使用一个结构模板,就需要使用带有标记的形式或者使用typedef

二.typedef 的作用

1.typedef的使用

typedef struct Simple  
{
	int a;
	int b;
	int c;
}simple;

可以使用 simple  代替 struct Simple 

//举例 用typedef 声明 初始化
typedef struct 
{
	int a;
	int b;
	int c;
}complex;

complex test = {2,4,7};

2.结构体的初始化

    struct Person  
    {  
        char *name;  
        int age;  
        double heigth;  
    };  

(1)定义的同时初始化

	  struct Person p1 = {"luban7hao",3,100};  

(2)先定义再逐个初始化

    struct Person p2;  
    p2.name = "luban8hao";  
    p2.age = 4;  
    p2.heigth = 101;  

(3)定义后全部初始化

    struct Person p3;  
    p3 = (struct Person){"luban9hap",5,102};  

 注意:

     结构体和数组在这里的区别,数组不能先定义再进行一次性初始化  

     结构体要明确的告诉系统{}中是一个结构体  

(4)将数据赋给指定的属性

	struct Person p4 = {.heigth=104, .name="luban10ha0", .age=6};  


3.结构体数组

(1)声明

struct book library[MAXBKS];

(2)示例

#include <stdio.h>

#define MAXTITL 40 
#define MAXAUTL 30
#define MAXBKS  100 /*最多书籍的册数*/

struct book 
{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};


int main(int argc, char const *argv[])
{
    struct book library[MAXBKS]; /*结构数组*/

    int count = 0;
    int index;

    printf("Please enter the book title.\n");
    printf("Press [enter] at the start of a line to stop.\n");

    while(count < MAXBKS && gets(library[count].title) != NULL && library[count].title[0] != '\0')
    {
        printf("Now enter the author.\n");
        gets(library[count].author);
        printf("Now enter the value.\n");
        scanf("%f", &library[count++].value);
        while(getchar() != '\n'){
             continue;
        }
        if (count < MAXBKS)
        {
            printf("Enter the next title.\n");
        }

    }
    if (count > 0)
    {
        printf("Here is the list of your books: \n");
        for (index = 0; index < count; index++)
        {
            printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
        }
    }else{
        printf("No books?Too bad.\n");
    }

    return 0;
}

4.结构体指针

(1)声明

struct guy *him; // 指向结构体的指针

(2)示例

#include <stdio.h>

#define LEN 20

struct names {
    char first[LEN];
    char last[LEN];
};

struct guy {
    struct names handle;
    char favfood[LEN];
    char job[LEN];
    float income;
};

int main(int argc, char const *argv[])
{
    struct guy fellows[2] = {   
        {
            {"Ewen", "Villard"},
            "grilled salmon",
            "personality coach",
            58112.00
        },
        {
            {"Rodney", "Swillbelly"},
            "tripe",
            "tabloid editor",
            2344422.00
        }
    };

    struct guy *him; // 指向结构体的指针
    printf("address #1: %p #2: %p\n", &fellows[0], &fellows[1]);
    him = &fellows[0];
    printf("pointer #1: %p #2: %p\n", him, him + 1);

    printf("him->income is $%.2f: (*him).income is $%.2f\n", him->income, (*him).income);
    printf("him->favfood is %s: him->handle.last is %s\n", him->favfood, him->handle.last);

    return 0;
}

5.访问结构体成员

访问成员,2种方式:

使用->,如him->favfood
使用(*him).income,注意必须用圆括号,因为.运算符比*的优先级更高


三.位段

1.定义与声明:

位段的声明与结构体类似,但是其成员是一个或者多个位的字段。这些不长度的字段实际上存储在一个或者多个的整形变量中。



2.位段的使用

struct Test
{
    unsigned int f1 :1; 
    unsigned int f2 :1; 
    unsigned int f3 :1; 
    unsigned int type :4;
    unsigned int index :9;
};

我们定义了一个结构 Test

该结构定义了五个成员。

第一个成员叫做 f1, 是 unsigned int 类型的。 规定了它以 1 位存放。

成员f2 和 f3 被定义为长度只有 1 位的。定义成员 type 占有 4 位。定义成员 index 占有 9 位。

C 编译器自动地把上面的位段定义压缩在一起。位段的划分如图所示。Test总共使用了 16 位。

这种方法的好处是, 定义成 Test类型的变量的位段, 可以如引用一般的结构成员一样方便地引用。同时, 使用了更少的内存单元数。

3.特殊情况

在包含位段的结构中, 也可以包括 "通常的" 数据类型。因此, 如果我们想定义一个结构, 它包含一个 int, 一个 char, 和二个 1 位的标志:

 

	struct Test
	{
		int a;
		int b;
		unsigned f1:1;
		unsigned f2:1;
	};

当位段出现在结构体中,被压缩成一个字,如果某个位段无法放入一个字中,则该字的剩余部分不用,直接跳入下一个字中。

举例:利用位段和联合体 完成Float To Int 转换

//参考博客 https://blog.csdn.net/huai1693838234/article/details/44804459  用C++实现
//float型数据在计算机中以IEEE754标准存储  
//32位长度,1位实数符号位(原码表示),1位指数符号位,7位指数位(此八位为移码表示)以及23位数据位(补码表示)

union  Bit
{
	float val;//将要强转的值
	struct H
	{
		//由于机器是小端
		//小端简单地说 就是高地址存高位 低地址存低位 结构体成员是向高地址增长的
		//所以用如下方式获取
		unsigned int tail:23;//获取val的最后23位 即尾码
		unsigned int offset:8;//获取val的中间8位 即阶码+偏移量
		unsigned int flag:1;//获取val的第一位 即符号位
	}H;
};
//abs()函数:求绝对值(整数)
//exp()函数:e的次幂函数(以e为底的x次方值)  在另一种方法求float to int 会使用到,此次作业暂时不涉及。
int FloatToInt2(float val)
{
	if(abs(val) < 0.000001)//如果为0值 直接返回
	{
		return 0;
	}
	int res;//保存返回值
	Bit temp;
	temp.val = val;
	int offset = temp.H.offset - 127;//获得偏移量
	res = temp.H.tail;
	res |= 0x00800000;//将丢弃的1填充回来
	res = res >> (23-offset);//移位操作 舍弃小数点后的数字
	if(temp.H.flag == 1)//负数
	{
		res = -res;
	}
	return res;
}
int main()
{
	printf("%d\n",FloatToInt2(-12.7));
	getchar();
	return 0;
}

使用位段时, 必须注意下列事项:
1.在某些机器上, 位段总是作为 unsigned 处理, 而不管它们是否被说明成 unsigned 的。
2.大多数C 编译器都不支持超过一个字长的位段。
3.位段不可标明维数; 即, 不能说明位段数组, 例如 flag:l[2]。
4.最后, 不可以取位段地址。原因是, 在这种情况不, 显然没有称作为 "位段指针" 类型的变量。

四.联合体

联合的声明与结构体类似,但是联合的所有成员 引用的是内存中相同的位置

不同时刻把不同的东西存储在同一个位置时,可以使用联合。

union (联合体)
{

}
sizeof(union)  //最大的一个元素的大小

五.枚举类型

enum abc { a,b,c,}
//如果给中间的值 例如:b 赋值 b=4 ,则再输出的时候只能给后面的值 c+1, 则c =5,而前面的a不能-1;
//就是一个常量和限制

六.关于内存对齐的使用规则

(1)前面的地址必须是后面的地址的整数倍,不是就补齐

(2)整个struct的长度必须是最长字节的正数倍!~~

(3)如程序中有#pragma pack(n)预编译指令,则所有成员对齐以n字节为准(即偏移量是n的整数倍),

不再考虑当前类型以及最大结构体内类型

注意:关于pragma pack(n)的使用  

(1)n必须是已有的大小 ,如:1,2,4,8 等

(2)如果指定的大小>默认的大小,是以默认的为准

(3)如果指定的大小<默认的大小,以指定的为准




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值