Summary
1)typedef并不是创立了一个新类型,而是给一个已有类型创立了一个新的名字
2)typedef次要用来简化类型名
和对立定义变量的形式
(重命名函数和数组)
3)struct用于自定义新类型
,可能将不同数据类型
的变量组成一个汇合
。struct创立新类型是一条非法的语句
,因而要以分号;
完结,外面的每个定义变量的语句,也都是以分号;
完结。
4)stuct构造体类型能够先申明再定义
(申明只是通知编译器构造体类型的新名字是什么,所以不定义也能够)。
如果只是前置类型申明
,然而还没有定义,这时候只能定义指针
(因为在定义变量的时候须要分配内存
,只有类型无奈确定变量大小;但能够定义指针,因为指针固定大小4字节或8字节)。
5)struct构造体类型能够省略类型名
,匿名构造体。两个匿名构造体的类型即便看起来一样,但依然是不同的两个构造体类型
。
6)struct构造体变量的实质是变量的汇合
,外面的成员占用独立的内存
。
7)union联合体也是C语言中用于自定义类型
的一个关键字,用法和struct很像。union与struct的不同之处在于:
- 不论union XX{}; 中有几个变量,所有的成员都
共享一段内存
,所有成员的起始地址都是雷同
的 - union XX{}; 占用的内存
大小取决于成员的最大类型
- union XX{}; 类型的变量只能以第一个成员类型的有效值进行
初始化
- 当取不同联合体里不同变量的值时,要
以相应的类型去解读这一段内存
8)小端系统
:低地址内存存储低位数据;大端系统
:低地址处存储高位数据;
union联合体能够用于判断零碎的大小端
:
int isLittleEndian(){ union { int i; char c; } test = {0}; test.i = 1; // 如果是小端系统,低地址就存低位数据,1就会存在低地址处 return (test.c == 1); // c只占一个字节,从低地址处取一个字节,应该失去1}
9)enum是C语言中的自定义类型
关键字,可能定义整形常量的汇合
类型。特点:第一个
枚举常量的默认值为0
;能够对任意枚举常量指定值(只能指定为整形
);后续常量的值默认在前一个值的根底上+1
;
enum类型的变量的实质依然是一个整形变量
。所以enum类型变量的大小为4
。
C语言中能够用任意一个整形值去初始化枚举变量(在C++中就必须用枚举值进行初始化,强类型)
10)古代程序设计中,内存应用的最小单元是字节
;有一些特定场合
,能够将比特位作为最小单元
应用内存:位域可能指定成员变量占用内存的比特位宽度
11)深刻位域
:位域的实质依然是一个构造体类型
位域成员必须是
整型
,默认状况下成员顺次排列struct Bits1{ int a : 16; short b : 8; char c : 8; // float f : 16; // error, bit-field ‘f’ has invalid type'位域的成员必须是整型!' float f; // 如果不应用 : 指定位域宽度,那么f就是一个非法的构造体成员};sizeof(Bits1) = 8; // a:2, b:1, c:1, f:4
位域成员占用的位数
不能超过类型宽度
struct Bits2{ char c : 16; // error: width of ‘c’ exceeds its type};
当存储位有余时,主动启用新单元
struct Bits3{ char a : 7; char b : 6;};sizeof(Bits3) = 2; // a占一个字节,b在a的字节里放不下了,只能用新的一个字节// 如果Bit3中再加一个char c;char c : 2; // 此时Bit3大小为2;因为c能够放到b所在的那个字节char c : 3; // 此时Bit3大小为3;因为c放到b所在的字节超出了,须启用新单元
能够应用
位域宽度0
来示意舍弃后面未应用的位,新启用一个字节struct Bits4{ char a : 7; char : 0; // 舍弃后面未应用的位 char b : 1;};sizeof(Bits4) = 2; // 两头的'char : 0'示意舍弃了a所在单元中剩下的位,在启用新的一个字节,所以大小为2;// 如果去除两头的'char : 0',则大小为1// 如果Bit3中再加一个char c;char c : 2; // 此时Bit3大小为2;因为c能够放到b所在的那个字节char c : 3; // 此时Bit3大小为3;因为c放到b所在的字节超出了,须启用新单元
1、typedef
问题:C语言中并没有提供字节类型
,如果咱们须要一个字节类型该怎么办?
类型命名关键字(typedef
)
- C语言中能够对类型赋予
新名字
语法:typedef Type NewTypeName;
留神:typedef并没有创立新类型,
只是创立了类型别名
typedef unsigned char byte;byte b = 128;char c = 128;
typedef的利用:
typedef常用语简化类型名,如
typedef unsigned char uint8;typedef int int32;typedef unsigned long long uint64;...
typedef罕用于定义类型名,可能以
对立的形式
创立变量(Type var; 如以ArrName arr;的模式来定义数组)typedef float(FArr5)[5]; // FArr5是一个数组类型:元素个数为5,元素类型是floattypedef int(IFuncII)(int, int); // IFuncII是一个函数类型:返回值是int,参数列表是(int, int)float _gArr[5] = {0};int add(int a, int b) {return a +b; }FArr5* pa = &_gArr; // 定义数组指针IFuncII* pf = add; // 定义函数指针int i = 0;for(i = 0; i<5; i++) printf("%f\n", (*pa)[i]); // 应用数组指针拜访数组 printf("%d\n", pf(i, i+1)); // 应用函数指针调用函数
2、struct
问题:C语言中是否能够创立不同数据类型变量的有序汇合?
2.1 构造体
- struct是C语言中
自定义类型
的关键字 struct可能定义
不同数据类型变量
的汇合
类型语法
struct TypeName{ Type1 var1; Type2 var2; ...};
语法示例:
struct Student{ char name[20]; int id; short major;};struct Student s1 = {"Zhangsan", 908, 1}; // 构造体变量初始化列表printf("s1.name = %s\n", s1.name);printf("s1.id = %d\n", s1.id);printf("s1.major= %d\n", s1.major);
深刻struct构造体类型
- struct构造体变量的实质是
变量的汇合
- struct构造体变量中的
成员占用独立的内存
- struct构造体类型能够用
typedef赋予新类型名
- 能够定义
struct构造体类型的指针
,并指向对应类型的变量
typedef struct Student Stu; // 1)struct Student还没有定义,就在后面定义新名字正当么?struct Student{ char name[20]; int id; short major;};// mainStu s = {{0}}; // 2)这种初始化形式能够么?Stu* ps = &s;strcpy(ps->name, "Lisi");ps->id = 1;ps->major = 825;// 释疑// 1)typedef struct Student Stu;只时一个申明,仅仅是申明struct Student这个类型能够用Stu来示意,所以不须要struct Student类型曾经定义了// 2)Stu s = {{0}};其实等价于Stu s = {{0}, 0, 0}。第一个成员用{0}初始化,前面没给的都用0初始化,相似于数组的初始化。字符串的实质是一个字符数组,所以能够用数组初始化的形式,用{0}初始化name。
struct能够定义无名构造体类型:
struct{ char name[20]; int id;} noname;
上面的代码是否正确?
struct { int a, b; } v1;struct { int a, b; } v2; struct { int a, b; }* pv;v1.a = 1; v1.b = 2;v2 = v1;pv = &v2;
这段代码在gcc编译时就会报错
!
v2 = v1; // error: 'incompatible types' when assigning to type 'struct <anonymous>' from type 'struct <anonymous>'pv = &v2; // warning: assignment from 'incompatible pointer type'
编译器的报错指出,v1 v2 *pv都是不同的构造体类型,不能间接进行互相赋值。阐明尽管v1和v2这两个匿名构造体看起来类型是一样的,存的变量也都一样,但实际上是不同的类型
!
2.2 位域
在古代程序中,内存应用的最小单位为字节
;在一些特定场合,能够将比特位作为最小单位
应用内存;构造体可能指定变量占用内存的比特位宽度
(位域)
位域示例
struct BW{ unsigned char a : 4; // a占用一个字节的4位宽度 unsigned char b : 2; // b占用一个字节的2位宽度 unsigned char c : 2; // c占用一个字节的2位宽度};struct BW bw;bw.a = 15; bw.b = 1; bw.c = 3;printf("sizeof(struct BW) = %d\n", sizeof(bw)); // 输入1
深刻位域:
位域成员必须是
整型
,默认状况下成员顺次排列struct Bits1{ int a : 16; short b : 8; char c : 8; // float f : 16; // error, bit-field ‘f’ has invalid type'位域的成员必须是整型!' float f; // 如果不应用 : 指定位域宽度,那么f就是一个非法的构造体成员};sizeof(Bits1) = 8; // a:2, b:1, c:1, f:4
位域成员占用的位数
不能超过类型宽度
struct Bits2{ char c : 16; // error: width of ‘c’ exceeds its type};
当存储位有余时,主动启用新单元
struct Bits3{ char a : 7; char b : 6;};sizeof(Bits3) = 2; // a占一个字节,b在a的字节里放不下了,只能用新的一个字节// 如果Bit3中再加一个char c;char c : 2; // 此时Bit3大小为2;因为c能够放到b所在的那个字节char c : 3; // 此时Bit3大小为3;因为c放到b所在的字节超出了,须启用新单元
能够应用位域宽度0来示意舍弃后面未应用的位,新启用一个字节
struct Bits4{ char a : 7; char : 0; // 舍弃后面未应用的位 char b : 1;};sizeof(Bits4) = 2; // 两头的'char : 0'示意舍弃了a所在单元中剩下的位,在启用新的一个字节,所以大小为2;// 如果去除两头的'char : 0',则大小为1// 如果Bit3中再加一个char c;char c : 2; // 此时Bit3大小为2;因为c能够放到b所在的那个字节char c : 3; // 此时Bit3大小为3;因为c放到b所在的字节超出了,须启用新单元
3、union
联合体 union
- union是C语言中的
自定义类型
关键字 - union是struct的兄弟关键字,
用法上十分类似
语法:
union TypeName{ Type1 var1; Type2 var2; ...};
union与struct的不同:
- union类型所有成员
共享一段内存
(所有成员起始地址雷同
) - union类型的
大小取决于成员的最大类型
- union类型的变量
只能以第一个成员类型的有效值进行初始化
union应用示例:
union Test{ int a; float f;};union Test t = {10}; // '只能以第一个成员类型的有效值进行初始化'printf("sizeof(union Test) = %d\n", sizeof(t)); // 4, '大小取决于成员的最大类型'printf("&t.a = %p\n", &t.a); // 0xbfb21f78 printf("&t.f = %p\n", &t.f); // 0xbfb21f78, '共享一段内存' '所有成员起始地址雷同'printf("t.a = %d\n", t.a); // 10, printf("t.f = %f\n", t.f); // 0.000000, 以浮点数类型去解读这个内存,天然不是预期的(浮点数在内存中的示意形式和整形不一样,详见C进阶)t.f = 987654321.0f;printf("t.a = %d\n", t.a); // 1315666339,同上,以整形的形式去解读一个示意浮点数的内存,天然不是预期的 printf("t.f = %f\n", t.f); // 987654336.000000,'浮点数在内存中的示意本就是不准确的',所以也不是预期的完全一致的(详见C进阶)
4、enum
C语言中的枚举类型 enum
- enum是C语言中的自定义类型关键字
- enum可能定义整形常量的汇合类型
语法:
enum TypeName{ IntConst1, IntConst2, ...};
enum注意事项:
第一个
枚举常量的默认值为0
- 后续的常量值在前一个常量值的根底上
加1
能够对任意枚举常量指定整型值(
只能指定整型值
)enum Day{MON = 1, TUE, WED, THU, FRI, SAT, SUN};enum Season{Spring, Summer = 3, Autumn, Winter = -1};
本文总结自“狄泰软件学院”唐佐林老师《C语言入门课程》。
如有错漏之处,恳请斧正。