目录
C语言为什么要引入这么多的数据类型呢?引入这么多的数据类型是为了更加方便的表现现实世界中事物,针对不同的数据,采取不同的存储方式和进行不同的处理。 这是C语言数据处理能力很强的原因也是C语言的一大特点。
C语言为我们提供了int, float等基本数据类型,这些都是表示基本数据用的。然而C语言也为我们提供了复杂的数据类型,比如struct, union类型等,这些是由基本数据类型通过组合或共用一块空间从而形成,可以对应现实世界的绝大部分难以描述的事物。
1.基本数据类型
int 整型 可以用来存放整。
char 字符型 可以用来存放本地字符集的一个整数。
double/float 双精度浮点/单精度浮点 型。
整型
注: 对于 long 或者 short 等限定符限定整型时,可以将 int 省略掉
字符型
注: 对于char类型取值范围到底是-128到127还是0到255取决于编译器类型
浮点型
关于浮点型精确
C标准规定float类型至少精确到小数点六位,double至少精确到小数
点后十位,而long double至少与double相同
关于浮点型创建
对于float类型变量传递参数时,C编译器会自动将float类型的值转换位double类型。
当我们需要float变量时,应:
int main()
{
float a = 1.3f;
return 0;
}
在这里,我们是用后缀f将1.3当作 float 类型,再传递给变量a;
关于e计数法:
C标准规定,单进度浮点类型储存方式如图,计算方式位(-1)^s*(m+1)*(e-127);
则e计数法如下图所示:
示例:
1.3e+10
1.3e-12
此时e前的1.3表示数,e+10,e-12分别表示10^10,10^(-12);
其正号可以省略,如:
1.35e10;
1.36e-4;
2.构造类型:
数组 用于存放多个相同类型的数据
结构体 用于存放多个可能不同类型的数据
共用体 用一块内存存放不同类型的数据
枚举类型 用于一些固定长度和固定数值的变量值范围便于系统使用
数组
示例:
int a[] = {1,2,3,4};
char b[] = "abcde";
char c[] = {'a','b','c'};
int d[20] = {1,2,3};
如图,可以将同一数据类型的数据按顺序存在相邻的地址中。
此时a表示{1,2,3,4}数组的首元素地址,该数组的所占内存大小时(元素数)*(int 类型大小)。
数组声明时可以省略[]里的数字,此时数组将会按照存入的数据开辟内存空间。
c对比b,在b数组的字符串结尾自动加入'\0',即数组b自动开辟的内存空间大小是6字节,而c数组不会在结尾加入'\0'。
结构体
关键字:struct
1)结构体定义和变量声明:
示例:
struct student
{
char name[20];
int age;
char sex[20];
};
struct student a;
代码的意思是定义一个叫student的结构体,里面有字符数组name,整形age,字符数组sex,并且可以声明student数据类型的变量a。
2)匿名结构体:
示例:
struct
{
char name[20];
int age;
char sex[20];
}student;
此时定义的是一个没有名字的结构体,同时声明一个变量student,由此方式创建的结构体只能在定义时声明变量,在定义之后无法再次声明变量。
3)嵌套结构体:
struct student
{
char name[20];
int age;
struct
{
char favorite[20];
};
}
这里定义了一个叫student的变量类型,并在变量类型中又定义一个结构体。
4)结构体引用:
我们可以通过数组名,使用名称+选择对象操作符(即 . )+结构体成员来引用结构体变量内容。
示例:
1.
struct student
{
char name[20];
int age;
char sex[20];
};
2.
struct student a;
3.
a.age = 1;
通过1:结构体定义,2:结构体声明变量后,通过3的a.name来访问引用a变量中name中储存的内容。
也可以使用结构体变量地址+成员选择指针操作符(->)+成员 来引用。
示例:
1.
struct student
{
char name[20];
int age;
char sex[20];
};
2.
struct student a;
3.
(&a) -> name = “wang";
这里成员选择指针操作符的优先级大于取地址操作符,所以将&a括号起来。
共用体(联合体):
关键字:union
共用体的创建,声明与结构体相似,我们直接来看结构体和共用体不同的地方:
如图所示,我们声明了一个结构体变量a,a在内存中开辟的内存是32,其中整形age占四个字节,字符数组name占20个字节,而sex[7]是7个字节,根据内存对齐的原则,需要多开辟一个字节,加起来共32个字节。
而共用体,运行结果是 20,可知共用体是选取内容成员中所需开辟最大空间的类型即 name[20] 来开辟空间的,也就是说,共用体的成员使用的是同一块内存空间。
枚举类型:
关键字: enum
示例:
enum week
{
Su, Mo, Tu, We, Th, Fr, Sa
};
定义枚举类型,当没有指定元素的值时,默认第一个元素为0,后续元素依次加1;
注:一个整数不能在定义外直接赋给枚举变量元素,需要强制类型转换;
3.指针类型
指针是一个值为内存地址的变量(或数据对象)。
1)指针声明和引用
示例:
int a = 1;
int* pa = &a;
声明一个整形变量a,赋值为1,再声明了一个整形指针变量pa,赋值为&a。
我们可以通过指针变量访问变量a的内容
示例:
int a = 1;
int* pa = &a;
int b = *pa;
使用解引用操作符(*)+指针类型变量来访问内存空间。
2)指针数组与数组指针:
对于指针数组和数组指针,容易弄迷糊,我们可以在指针和数组之间加一个 的字,如数组的指针,指针的数组
示例:
int a[] = {1,2,3,4,5};
int(*pa)[] = a;
此时的pa优先和解引用操作符(*)结合,再与数组下标操作符([])结合,此时的指针指向的是一个数组。
int a[] = {1,2,3,4,5};
int b[] = {6,7,8,9,10};
int *pa[2] = {a,b};
在这里数组下标操作符优先级大于解引用操作符,所以pa不是指向一个数组的指针,而是一个存放指针的数组。
3)指针的运算
指针+/-整数:
int*a = NULL;
a+=1;
char*b = NULL;
b+=1;
这里由于a是整形变量,所以经过a+=1后,a的值上升4个字节,而b是字符类型变量,经过b+=1后值只上升1个字节,也就是说,指针+/-整数时,指针变量的变化大小取决于指针类型。
指针 - 指针
int a[] = {1,2,3,4,5};
int b = &a[4] - &a[0]
经过编译并运行,b的值为4,由此我们可以得出,指针 - 指针 可以得到两个指针之间的元素数。
指针的关系运算
简单来说就是用关系运算符(>或<)来比较指针大小。
4.空类型 void
通常用于函数的形参定义,返回值为void的函数。