C语言的文件类型:
.h 头文件
.c 源文件
.i 预处理文件
.o 目标文件
.s 汇编文件
.a 静态库文件
.so 动态库文件,相当于windows系统里的.dll
.gch 头文件的编译结果,没什么用,建议立即删除
C语言的基本数据类型:
为什么划分数据类型:
数据存储计算机中需要耗费存储空间(内存、硬盘),在编程语言中把数据按照使用范围、特点划分为不同的种类,根据要解决的问题选择合适的数据,这样可以节约存储空间、提高运算速度。
整型:不带小数点的数据
有符号整型:最高位的二进制位用来表示正负,0代表整数,1代表负责。
由于编程时使用的较多,所以编译器允许 signed 不加就代表加,可以省略。
signed char 1 -128 ~ 127
signed short 2 -32768 ~ 32767
signed int 4 -2147483648 ~ 2147483647
signed long 4|8
signed long long 8 -9223372036854775808 ~ 9223372036854775807
无符号整型:所以有二进制位都用来表示数据,因此只能表示正数。
在使用时 unsigned 关键字不能省略,所以比较麻烦,C语言的标准委员会为了我们方便使用无符号整型,在stdin.h头文件中对无符号整型进行了重定义。
uint8_t,uint16_t,uint32_t,uint64_t
unsigned char 1 255
unsigned short 2 65535
unsigned int 4 4294967295
unsigned long 4|8
unsigned long long 8 18446744073709551615
注意:signed long、unsigned long 在32位Linux系统下是4字节,64位Linux系统下是8字节。windows系统都是4字节。
浮点型:小数点是浮动,也就是带小数点的数据。
小数后六位有效,采用科学计算法存储,由:符号位+底数位+指针数构成,由于格式比较特殊所以在使用时需要进行格式转换,所以运算速度比整型慢,编程时尽量少用。
单精度:float 4
双精度:double 8
高精度:long double 12|16
if(0.000001 > f && f > -0.000001) // 判断"零值"
布尔:由于先出现的C语言,后有的布尔类型,所以在设计C语言时没有设计布尔类型,之后C语言以打补丁的方式增加了布尔类型。
使用布尔类型时需要包含stdbool.h头文件,才能使用 bool true false
bool 1字节
ture 4字节 ---->整数1
false 4字节 ---->整数0
printf("%d %d %d\n",sizeof(bool),sizeof(ture),sizeof(false));
用gcc编译器编译输出结果 1 4 4
用g++编译器编译输出结果为 1 1 1
字符型:字符就是符号或图案,但在计算机中是以整数存储的,当需要显示时会根据ASCII表中的对应关系显示出相应的符号或图案,也就是说字符就是使用整数模拟的。
'\0' 0
'0' 48
'A' 65
'a' 97
总结:编程语言之所以把数据进行分类,是因为当使用合适的数据类型存储合适的数据可以提高代码的运行速度并节约内存,要了解各数据类型的特点、取值范围,在编程时选择合适的数据类型。
变量:
什么是变量:在程序运行过程中可以变量的量,用来存储数据的容器。
变量的定义: 数据类型 变量名;
1、变量的默认值是随机的、不确定的,一些特殊用途的变量需要初始化,比如:求和、计数的。
2、变量的取名规则:
1、由字母、数字、下划线组成,不能使用特殊符号。
2、不能以数字开头。
3、不能与关键字(C语言中的32个关键字,要会默写)重名。
4、见名知意(功能+类型+使用范围)。
变量的使用:
存储数据:变量名 = 1234;
参与运算:printf("%d\n",变量*3-2);
变量的输出:
C语言使用printf/scanf系列函数输入、输出变量的值,需要提供变量名字和类型,C语言使用占位符告诉printf/scanf变量的类型。
占位符:%c %hhu %hu %u %lu %llu %hhd %hd %d %ld %lld %f %lf %Lf
printf("提示信息+占位符+转义字符",变量名);
变量的输入:
scanf("占位符",&变量的地址),&变量名 可以计算出变量的地址。
注意:现阶段scanf的双引号中,除占符什么都不要加。
常量:
常量就在程序运行过程中不能改变的量,C语言中的常量有:字面值常量、宏常量、枚举常量
'A' char 类型的字面值常量
100 int 类型的字面值常量
3.14 double 类型的字面值常量
100u unsigned int类型的字面值常量
100lu unsigned long类型的字面值常量
100llu unsigned long long类型的字面值常量
3.14f float 类型的字面值常量
3.14l long double 类型的字面值常量
注意:long类型 Linux32 4字节 Linux64 8字节 windows系统 4字节
limits.h 头文件中定义了各类型的最大值和最小值宏。
格式化输出:
以下这种占位符的用法只是为了让数据显示的更整齐,了解即可。
%nd 数据至少显示n个字符宽度,不够则补空格,默认右对齐。
%-nd 数据至少显示n个字符宽度,不够则补空格,左对齐。
%0nd 数据至少显示n个字符宽度,不够则补0,右对齐。
%.mf 小数点后显示m位,不够则补0,多余的数据四舍五入。
%n.mf 小数点后显示m位,不够则补0,多余的数据四舍五入,数据至少显示n个字符宽度,不够则补空格,默认右对齐。
%-n.mf 小数点后显示m位,不够则补0,多余的数据四舍五入,数据至少显示n个字符宽度,不够则补空格,左对齐。
%0n.mf 小数点后显示m位,不够则补0,多余的数据四舍五入,数据至少显示n个字符宽度,不够则补0,右对齐。
%g 按实际情况显示小数点后的数据,不显示多余的0。
运算符:
算术运算符:+ - * / %
整型使用/运算时,结果会省略小数点,例如:2/3 得到的结果是0。
/ % 都是进行除法运算,/运算结果是商,%运算结果是余数,但它们的除数都不为0。浮点数的数据不能使用%运算符。
如果除以字面值0,编译器会有警告但不会报错,程序运行时会出现"浮点数例外,核心已经转储"错误,程序会提前结束不能再继续执行。
关系运算符:> < >= <= == !=
它们的运算结果是布尔值,但C语言中没有真正的布尔类型,所以使用0代表false,1代表true。
10 < num < 100 该表达式在数学中表示的是num的取值范围,但在C语言中它的运算结果永远为真,关系运算符的运算规则与数学中的不同。
在C言语表示num的取值范围:10 < num && num < 100
使用==运算符时,要把变量放在右边,常量放在左边,这样能防止少写一个=的情况:
100 == num; 100 = num; 这样编译器会报错
num == 100; num = 100; 这样就变成的赋值语句
逻辑运算符:&& || !
会先把运算对象转换成布尔值,0值转换成假,非0值转换成真,再进行计算。
A && B 与 一假即假
A || B 或 一真即真
!A 求反,它是单目运算符,比所有的双目运算符级别都高。
短路特性:当逻辑表达式的左边已经可以确定结果,右边的不再计算,合理的使用短路特性可以实现精简的if语句。
if(num > 100)
{
num = 0;
}
num > 100 && (num = 0);此代码与上面的if语句功能相同,但不建议使用,因为可读性比较低。
自变运算符:++/--
它们是单目运算符,运算对象必须是变量,可以让变量的值自动加1或减1。
前自变:++/--i 变量i的值会立即加1、减1。
后自变:i++/-- 变量的值不会立即变化,会在下一行代码执行前加1、减1。
三目运算符:[1] ? [2] : [3];
由于它的运算对象有三个,所以叫三目运行符,也是唯一的三目运算符。
首先把[1]部分转换成布尔值,为真执行[2],为假则执行[3],相当于精简的 if else 结构。
注意:三目运算符中不能使用 break、continue、return、goto 等语句,因为三目运算符构成的是表达式,必须有计算结果,所以不能中途跳转。
赋值运算符:= += *= /= …
num += 10 <=> num = num + 10;
num /= 10 <=> num = num / 10;
字节运算符:sizeof
它不是函数,如果运算对象不是表达,它可以不使用小括号,它是C语言的32个关键字之一,用于计算数据类型在内存中占用的字节数。
注意:它不计算小括号中的表达式,只是推演一处运算结果是什么类型,然后计算出在内存中占用的字节数。
int num = 1234;
printf("%d\n",sizeof(num=6666));
printf("%d\n",num); // 执行结果是1234
printf("%d\n",sizeof(num>10:'A':3.14)); // 结果是8
位运算符:
该类型的运算符需要进制转换、原码、反码、补码方面的知识,后期再讲。
类型转换:
前提:只有相同类型的数据才能在一起运算,不同类型组成的表达式必须先转换成同一种类型(自动)再进行计算。
自动类型转换(隐式类型转换):
1、以不丢失数据为基础。
2、字节数少的向字节数多的转换。
3、有符号向无符号转换。
long num1 = -100;
unsigned long num2 = 33;
(num1+num2 > 0)? printf("大于零") : printf("小于零"); // 结果大于零
4、整型向浮点型转换。
5、char 和 short 会优先转换int类型再考虑是否需要继续转换。
short num1 = -100;
unsigned short num2 = 33;
printf("%d\n",sizeof(num1+num2)); // 结果是4
自动类型转换就是编译器默默地、隐式地、偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生。
1) 将一种类型的数据赋值给另外一种类型的变量时就会发生自动类型转换,例如:
float f = 100;
100 是 int 类型的数据,需要先转换为 float 类型才能赋值给变量 f。再如:
int n = f;
f 是 float 类型的数据,需要先转换为 int 类型才能赋值给变量 n。
在赋值运算中,赋值号两边的数据类型不同时,需要把右边表达式的类型转换为左边变量的类型,这可能会导致数据失真,或者精度降低;所以说,自动类型转换并不一定是安全的。对于不安全的类型转换,编译器一般会给出警告。
2) 在不同类型的混合运算中,编译器也会自动地转换数据类型,将参与运算的所有数据先转换为同一种类型,然后再进行计算。转换的规则如下:
- 转换按数据长度增加的方向进行,以保证数值不失真,或者精度不降低。例如,int 和 long 参与运算时,先把 int 类型的数据转成 long 类型后再进行运算。
- 所有的浮点运算都是以双精度进行的,即使运算中只有 float 类型,也要先转换为 double 类型,才能进行运算。
- char 和 short 参与运算时,必须先转换成 int 类型。
下图对这种转换规则进行了更加形象地描述:
unsigned 也即 unsigned int,此时可以省略 int,只写 unsigned。
自动类型转换示例:
- #include<stdio.h>
- intmain(){
- floatPI =3.14159;
- ints1,r =5;
- doubles2;
- s1 =r *r *PI;
- s2 =r *r *PI;
- printf("s1=%d, s2=%f\n",s1,s2);
- return0;
- }
运行结果:
s1=78, s2=78.539749
强制类型转换:
(目标类型)数据,会把数据强制转换成目标类型,但这种转换出的结果可能出现数据丢失,慎重使用。