C数据类型和组合类型(结构、联合、枚举和typedef)

注:《C primer plus》笔记

一、基本类型:

    有符号整数
    int:系统的基本整数类型。C保证int类型至少有16位长(2字节),具体长度视系统和硬件而定。(位是二进制位)
    long:这种类型的整数保证最小位数不低于int类型,可能比int多偶数个字节。long int
    short:这种类型保证最少有16位,并且不能多于int类型的位长。short int
    long long:这种类型保证位长不低于long类型并且至少有64位长。long long int
    无符号整数
    unsigned int;unsigned long;unsigned short:无符号的整数,比有符号的整数多出来一个表示正负的位来表示数值,所以它可以表示更大一位的数值,但是不能表示负数。
    字符
    char:使用一个字节保存该字符的ASCII码(整数),所以可以进行加减等运算。
    布尔值
    _Bool:值为1(真)和0(假),该头文件有b变量true和false来表示真假。
    实浮点数
    float:系统的基本浮点类型。至少能精确表示6位有效数字。
    double:范围(可能)更大的浮点类型。能表示比float类型更多的有效数字(至少10位,通常会更多)以及更大的指数。
    long double:范围(可能)再大的浮点类型。能表示比double类型更多的有效数字以及更大的指数。
    复数和虚浮点数
    float _Complex:
    double _Complex:
    long double _Complex:
    float _Imaginary:
    double _Imaginary:
    long double _Imaginary:
    
二、衍生类型:
    数组:多个相同基本类型数据的集合,如果有N个同类数据形成的数组,那么他们的序号就是从0~N-1,引用元素使用:数组名[元素位],更可以使用多维数组。
    字符串:特指以'\n'字符结尾的字符数组。
    指针:存储数据的地址,对变量使用:&变量,获得变量的指针,对指针使用:*指针,获得该地址中存储的数据值。指针也可以形成数组。
    结构:某个对象具有不同数据类型的属性,这时候使用数组不能很好地表示,就可以使用结构了,结构也可以是变量。引用方式:结构名.属性。
    联合:是在某一个存储空间里,可以存储不同类型的数据,但是同一时间,该存储空间只能存放一种类型的数据的数据类型。


结构定义:
struct 结构类型名 {
    声明属性1;//例如char title[40];
    声明属性2;//例如char authoer[40];
    ......
};
声明结构:
struct 结构类型名 结构变量名;
引用结构:
结构变量名.属性1 = "test1";
puts(结构变量名.属性2);

结构变量在内存中的存储结构为:
就使用上而言,可以简单地视为结构定义产生了一个新的类型。

可以在结构定义时创建结构变量名。
struct book {
...
...
}library;

或者在声明结构变量时直接对其属性赋值,注意,赋值时,属性之间逗号分隔。
struct book library = {
    "a book",
    "Jack,
    15.5
};
或者指定初始化某个属性。
struct book test1 { .value = 10.99 };
或者按照任意顺序初始化某些属性。
struct book test2 { .value = 25.55,.author = "hank",.title = "Road" };
或者对一个属性多次初始化,但是只取最后一个值生效。
或者对指定属性初始化后,进行不指定属性的初始化,将会对指定属性的下一个属性进行初始化。
struct book test3 { .author = "boy",4.44};//下一个属性value被初始化为4.44

结构数组
若干个结构组成的数组。
结构数组定义和声明
struct book {
    char titile[30];
    char author[30];
    float value;
};
struct book library[100];

嵌套结构
struct name {
属性1;
属性2;
};
struct friend {
struct name hank;
属性4;
属性5;
};
引用friend的hank的属性1,可以使用friend.hank.属性1
注意:属性也可以成为成员。

指向结构的指针
struct book test;
struct book * ptr;
ptr = &test;
注意:结构变量名不像数组那样,是首个元素的地址。
利用指针访问属性:
ptr->属性1
->就相当于使用变量名的小数点。

数组不允许直接被另一个数组赋值,但是,结构可以直接被另一个结构赋值,即便结构中有属性是数组。
jiegou1 = jiegou2;
也可以初始化的时候直接赋值为了那个一个结构变量。
struct names h1 = {"dsajkd","dsadsa"};
struct names h2 = h1;

结构不仅可以作为参数传入函数,也可以作为返回值从函数返回,这就为多值返回,继指针之后,提供了又一种方法。

C99具有一个称为伸缩性数组成员(变长数组)的新特性。利用这一新特性可以声明最后一个成员是一个具有特殊属性的数组的结构。
该结构规则如下:
1,伸缩性数组成员必须是最后一个数组。
2,结构中必须至少有一个其他成员。
3,伸缩性数组就像普通数组一样被声明,除了它的方括号是空的。
示例如下:
struct flex {
    int count;
    double average;
    double scores[];
 };
声明一个struct flex类型的变量之后,您不能立刻使用scores做任何事情,因为还没有为它分配任何内存空间。C99的意图是希望利用这种特性声明一个指向struct flex类型的指针,然后使用malloc()来分配足够的空间,以存放struct flex结构的常规内容和伸缩性数组成员需要的任何额外空间。例如,假设想要用scores表示含有5个double类型数值的数组,可以如下操作:
struct flex * pf;//声明一个struct flex类型的指针。
pf = malloc(sizeof(struct flex) + 5 * sizeof(double));//分配内存
pf->count = 5;//指针方式对结构的属性赋值
pf->scores[2] = 18.5;//指针方式对结构的伸缩性数组成员赋值;
free(pf);//注意释放malloc()分配的内存。

因为结构保存不同类型的数据,所以使用结构来进行数据库编程是不错的选择。
结构的存在,为各种算法提供了土壤,例如二叉树。

联合
    是在某一个存储空间里,可以存储不同类型的数据,但是同一时间,该存储空间只能存放一种类型的数据的数据类型。
联合和结构一样,需要事先定义模板
union hoid {
    int digit;
    double bigfl;
    char letter;
};
含义是,联合名为hold,可以存储int类型的值,赋予变量digit。可以从年初double类型的值,赋予变量bigfl,可以存储char类型的值,赋予变量letter;结构的大小以其最大的某个声明变量一致,本例为double类型,即8字节(不同硬件和系统,可能有差异)。
下面声明联合变量
union hold fit;//hold类型的联合变量
union hold save[10];//10个联合变量的数组
union hold * pu;//指向hold类型变量的指针
联合的引用和赋值与结构类似,以小数点为链接,可以将联合的属性(成员)赋值给联合的属性(成员),也可以将联合赋值给联合。
union hold valA;
valA.letter = 'R';//
union hold valB = valA;//联合赋值给联合
union hold valC = {88};//将值赋值给与联合中的成员(属性)类型一致的变量。
union hold valD = {.bigfl = 118.2};//直接指定赋值给某个属性。
联合同时只能有一个属性(成员)有值存在:
fit.digit = 23;//存储区中存储int类型数据23
fit.bigfl = 2.0;//清除该存储区已有的数据,存储double类型数据2.0
fit.letter = 'h';//再次清理存储区,存储char类型数据h
联合指针的引用和结构类型,也是使用符号->
pu = &fit;
int x = pu->digit;

联合这种数据类型,可以表示某个对象的某个特征正处于什么状态,当然,特征有许多中,当状态却只有一种,这就是联合的用法。联合结合结构使用在某些实例中有不错的效果。

枚举
    创建一个int或char类型的数据类型,该数据类型的值为其定义或初始化的时候的范围,并不可跳出。使用枚举的目的是提高程序的可读性。
enum spectrum {red,orange,yellow,green,blue,violet};//初始化枚举spectrum的初始值,其中red等是常量,并不需要其他定义声明,就可以放在程序开头。
enum spectrum color;//声明枚举spectrum类型的变量color。
red如果定义为char类型,则不可移植到c++,因此,最好是定义为int类型。
下面是使用示例:
color = blue;
for(color = red;color <= violet;color++)
...
如果将red等格式化为%d打印,则可以看到,从第一个到最后一个常量,值都是从0开始依次增加1,这是枚举类型的默认值。
当然,也可以在初始化枚举时指定常量的值。
enum levels {low = 100,medium = 500,high = 2000};
如果只指定了部分常量的值,那么在前面的会按照最初的从0开始的方式初始化,后面的会按照已经给出的值依次加1来初始化
enum feline {cat,lynb = 10,psm,ti};
其中cat被初始化为0,psm,ti分别为11,12.

typedef
    typedef是一种高级数据特性,它使您能够为某一类型创建您自己的名字(类型别名定义)。
typedef与#define的区别:
1,与#define不同,typedef给出的符号名称仅限于对类型,而不是对值。
2,typedef的解释由编译器,而不是预处理器执行。
3,虽然typedef的范围有限,但是在这个范围内,typedef比#define灵活。
示例,单个字节的数值,其类型名称进行别名化
typedef unsigned char BYTE;//类型别名定义
BYTE x,y[10],*z;//使用别名进行数据变量的定义。

typedef定义的类型别名有效范围,和变量定义一样,都分为静态或自动(或者说全局或局部)。可以套用变量的作用域等来看待类型别名。
typedef可以增加程序的移植性,因为只需在程序头部进行定义的修改,即可实现全篇类型别名的类型的修改。
另外,#define也可以实现类型别名,但是功能上和typedef有一定区别:
#define STRING char *
typedef STR char *;
STRING name,sign;//实现char * name,sign只能将第一个变量声明为指针,而无法作用于第二个变量。
STR na,si;//实现char * na,* si,可以作用于本行的所有变量。

typedef也可以作用于结构、联合等。



 


你可能感兴趣的:(C,学习笔记,c,编程)