自定义类型:结构体、位段、枚举、联合

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>

//1 结构体
//结构是一些值的集合,这些值称为结构体成员,结构体的每个成员可以是不同类型的变量

struct Stu
{
    char name[20];
    int age;
    char sex[5];
    char id[20];
};
//结构体的自引用

struct Node
{
    int data;
    struct Node next;
};//错误的,结构体内不能包含结构体自身

struct Node
{
    int data;
    struct Node* next;

};//正确  指针是四个字节

//结构体内存对齐

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

int main()
{
    struct Test t;
    printf("&t=%p\n",&t);
    printf("&t.a=%p\n",&t.a);
    printf("&t.b=%p\n",&t.b);
    printf("&t.c=%p\n",&t.c);
    printf("&t.d=%p\n",&t.d);
    printf("sizeof=%d\n",sizeof(t));//16
    system("pause");
    return 0;
}

struct Test2
{
    char a;
    int b;
    int c;
    int d;
};

int main()
{
    struct Test2 t;
    printf("&t=%p\n",&t);
    printf("&t.a=%p\n",&t.a);
    printf("&t.b=%p\n",&t.b);
    printf("&t.c=%p\n",&t.c);
    printf("&t.d=%p\n",&t.d);
    printf("sizeof=%d\n",sizeof(t));//16
    system("pause");
    return 0;
}


struct Test3
{
    char a;
    char b;
    int c;
    int d;
};//12


struct Test3
{
    char a;
    char b;
    char c;
    int d;
};//8

//结构体对齐原则
//(1)第一个成员在与结构体变量偏移量为0的地址处
//(2)其他成员变量要对齐到某个数字的整数倍的地址处
// 对齐数=编译器默认的一个对齐数与该成员大小的较小值,vs中默认的值为8
//(3)结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍

//结构体修改默认对齐数
//对于跨平台的程序来说比较有意义
#pragma pack(1)//修改默认对齐数,对齐数改为1
struct Test
{
    char a;//1
    char c;//1
    int b;//1
};//运行结果为什么是6

//#pragma pack()//不加参数意味着对齐数恢复默认值

//计算结构体中某变量相对于首地址的偏移
struct test2
{
    char a;
    int b;
};

int main()
{
    struct test2 t2;
    (char*)&t2.b-(char*)&t2;//&t2.b的类型为int*,&t2的类型为struct test2*,两者相减结果为相差元素的个数
    system("pause");
    return 0;
}

//结构体传参
//结构体传参时要传结构体的地址


//2 位段
//位段的成员必须是int\unsigned int\signed int
//位段的成员后面有一个冒号和一个数字
//A是一个位段类型   ???

struct A
{
    int _a:2;//表示a占两个比特位,所表示的数字范围是0-3
    int _b:5;//表示b占5个比特位,所表示的数字范围是0-31
    int _c:10;
};
//使用位段时应注意跨平台问题


//3 枚举

enum Sex   //enum Sex为一种类型
{
    MALE,
    FEMALE,
    UNKNOWN,

};

int main()
{
    enum Sex s=MALE;
    //s=100;//编译是错的
    //printf("%d\n",s+10);//不合理,枚举不应支持加减乘除的计算
    printf("%d\n",s);
    system("pause");
    return 0;
}


//4 联合
//联合体的成员是共用同一块内存空间
union Un
{
    char a;
    int b;
};

int main()
{
    union Un un;
    //printf("%p\n",&un);
    //printf("%p\n",&un.a);
    //printf("%p\n",&un.b);//a和b在同一地址上

    un.b=0x11223344;
    un.a=0x55;
    //结果b=0x11223355,原因是改变a的地址会影响b的地址
    system("pause");
    return 0;

}


//联合的应用
//1 IP地址的表达
union IP
{
    uint32_t data;
    struct Dec
    {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    }dec;
};

int main()
{
    union IP ip;
    ip.data=0x11223344;
    printf("%d.%d.%d.%d\n",ip.dec.a,ip.dec.b,ip.dec.c,ip.dec.d);
    system("pause");
    return 0;
}

//判断大小端

int IslittleEnd()
{
    int a=1;
    char* b=(char*)&a;
    if(*b==1)      //为什么是*b
    {
        return 1;
    }
    return 0;
}

//2 用联合体来计算大小端

union Un
{
    char a;
    int b;
};

int IslittleEnd()
{
    union Un u;
    u.b=0x1;
    if(u.a==0x1)
    {
        return 1;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值