C语言简介:
BCPL->newB->C->UNIX->Minix->Linux->gcc
C语言诞生于1971~1973年,在肯.汤普逊和丹尼斯.里奇领导下编写完成,
归属于美国的贝尔实验室。
C语言为了专门编写操作系统而诞生的语言,所以天生适合对硬件编程,
也因为速度快而著称,也非常适合实现数据结构和算法。
由于出现时间早,有很多缺陷,也没想过普通人能使用C语言编程,因此
存在着缺陷,但是前辈总结了一些可以避免的经验《C陷阱与缺陷》
《C程序设计语言》
自由源于自律
C89语法标准,也是gcc默认的语法标准
C99语法标准,对C语言的扩展和增强 -std=gnu99
C11语法标准,全新的升级
一、第一个C程序
#include <stdio.h>
程序员所编写的代码不是标准的C代码,需要一个程序翻译它,变成标准的C代码,负责翻译的程序叫做预处理器,翻译的过程叫做预处理,被翻译的代码叫做预处理指令,以#开头都叫做预处理指令。
#include 的功能是把一个头文件导入到当前文件中
#include <xxx.h> 从系统指定的路径下加载头文件
#include “xxx.h” 先从当前工作路径下加载头文件,如果没有则再从系统指定路径加载头文件
stdio.h
头文件:以.h结尾,里面储存一些辅助性代码,绝大多数都是函数的声明(也就是函数的开头)
源文件:以.c结尾,里面记录的是功能性代码
C语言标准委员会为C语言以函数形式提供了一套基础的功能,这些函数就被封装libc.so库中,很多头文件负责对libc.so进行说明,stdio.h就是其中一个,常用string.h stdlib.h
stradard input output 负责对输入输出功能函数的说明
int main()
{
printf(“Hello World!\n”);
return 0;
}
main函数:
C语言中以函数为单位来管理代码,一个函数就是一段具有某个功能的代码的集合
main函数是程序的执行入口,有且只能有一个
int 是一种数据类型,它表示main的执行结果是一个整数
return 有两个功能:
1、返回一个数给函数的调用者(main是给操作系统)
2、结束函数的执行
main函数的调用者是操作系统,它的返回值给了操作系统,反映了程序是如何结束的,通常有三种:
正数 出现异常 (别人的错误)
0 一切正常
负数 出现错误 (自己的错误)
echo $? 可以查看上一个main函数的返回值
printf/scanf是标准库中的函数,负责输入、输出数据,用来调试程序
转义字符:键盘上有一些没有的符号,用一些特殊的字符来表示,这些特殊的字符就叫转义字符,\n 就是其中一个。
\t 制表符tab
\r 回到行首
\b 退格键
\a 铃响
\
%% %
C语言以分号作为一行代码的结束,使用大括号来划分区域
二、C代码变成可执行程序的过程:
1、预处理:把源文件翻译成预处理文件
gcc -E code.c 显示预处理结果到终端
gcc -E code.c -o code.i 生成以.i结尾的预处理文件
2、编译:把预处理文件编译成汇编文件
gcc -S code.i 生成以.s结尾的汇编文件
3、汇编:把汇编文件翻译成二进制的目标文件
gcc -c code.s 生成以.o结尾的目标文件
4、链接:把若干个目标文件合并成一个可执行程序
gcc code.o 生成默认名是a.out的可执行程序
C语言中文件类型:
.h 头文件
.h.gch 头文件的编译结果,它会被优先使用
.c 源文件
.i 预处理文件
.s 汇编文件
.o 目标文件
.a 静态库
.os 共享库
三、编译器
负责把人能看懂的记录代码的文本文件,翻译成计算机能看懂的二进制文件,由预处理器、编译器、链接器组成。
gcc是又GNU社区为了编译Linux代码而开发的一款免费的编译器,采用默认是C89标准,-std=gnu99来设置C99标准
常用的参数:
-E:显示预处理结果
-S:生成汇编代码
-c:只编译不链接
-o:设置编译结果的名字
-I:指定头文件的加载路径
-l:指定要使用的库,-lm,使用数据库
-Wall:以严格的标准来检查代码,用来显示更多的警告提醒
-Werror:把警告当错误处理
-std:指定编译的语法标准
储存空间的单位:
Bit 比特 一个二进制位,只能储存0或1,计算机储存数据的最小单位
Byte 字节 八个二进制位,计算机储存器的存储容量的基本单位
KB 1024字节
MB 1024KB
GB 1024MB
TB 1024GB
PB 1024PB
四、数据类型
为什么要对数据进行分类:
1、现实社会中的数据自带类别属性
2、对数据进行分类可以节约储存空间、提高运行效率
C语言中的数据分为两大类:自建(程序员自己设计的,例如:结构、联合、枚举、类)和内建(C语言自带)。
整型:
signed 有符号
signed char 1 -128~127
signed short 2 -32768~32767
signed int 4 正负20亿
signed long 4/8 正负20亿/9开头的19位数
signed long long 8 9开头的19位数
注意:signed 不加就代表加了
unsigned 无符号
unsigned char 1 0~255
unsigned short 2 0~65535
unsigned int 4 0~40亿
unsigned long 4/8
unsigned long long 8 1开头的20位数
注意:由于定义无符号数据比较麻烦,标准库把这些无符号的类型重新定义成以下类型:
需要包含头文件<stdint.h>
uint8_t、uint16_t、uint32_t、uint64_t
int8_t、int16_t、int32_t、int64_t
浮点型:
float 4
double 8
long double 12/16
注意:采用科学计数法,二进制与真实的数据之间需要翻译,因此计算浮点型要比整型慢,编程时能尽量使用整型
小数点后6位有效
模拟:
char:字符 其实是图案或者是符号,在内存中储存的是整数,需要显示时,根据ASCII码表,找到该整数对应的符号或图案,然后显示。
0 == '\0'
48 == '0'
65 == 'A'
97 == 'a'
bool 布尔 先有了C才有了bool类型,所以C语言是不可能有真正的布尔类型,stdbool.h头文件对布尔类型进行了模拟
bool true false
可以使用sizeof来计算类型的字节数
五、变量与常量
什么是变量:程序运行期间数值可以变化的叫做变量,相当于储存数据的盒子
定义:类型 变量名;
int num;
取名规则:
1、由字母、数字、下划线组成
2、不能以数字作为开头
3、不能与32个关键字重名、能够默写
4、见名知意(功能、类型、作用范围)
unsigned char num_u_c
printf scanf bool sizeof
注意:变量定义时,一定要初始化(习惯),否则值是不确定的
使用:
赋值: num = 10;
参与运算: num * 10;
变量的输入、输出:
int printf(const char *format, ...);
功能:输出数据
format:双引号包含的格式信息(提示信息+占位符)
...:变量的列表
返回值:输出字符的个数
int scanf(const char *format, ...);
int ret = scanf()
功能:输入数据
format:双引号包含的格式信息(占位符)
...:变量的地址列表,变量的地址 = &变量名
返回值:成功输入的变量的个数
练习1:定义各种类型的变量并初始化,使用printf来显示
练习2:定义各种类型的变量并初始化为0,使用scanf来输入,printf来显示
类型占位符:C语言中通过占位符的方式来传递变量的类型
%hhd %hd %d %ld %lld
%hhu %hu %u %lu %llu
%f %lf %LF
什么是常量:程序运行期间数值不能发生变化的叫常量
字面值常量
100 默认int
100l long
100ll long long
100u unsigned int
100lu unsigned long
100llu unsigned long long
3.14 默认double类型
3.14f float
3.14l long double
六、格式化输入输出
%nd 显示n个字符宽度,不够则补空格,右对齐
%-nd 显示n个字符宽度,不够则补空格,左对齐
%0nd 显示n个字符宽度,不够则补0,右对齐
%n.mf 显示n个字符宽度(小数点算一位),不够补空格,m表示小数点后m位,不够补0(四舍五入)
%g 不显示小数点后多余的0
七、运算符
自变运算符:++/-- 使变量的值自动+1或者-1
前自变:立即生效
后自变:下一语句才生效
注意:不要在一行中出现多个++ --,很危险
printf("%d%d%d",num++,num++,++num);
算术运算符:+ - * / %
/ % :除数不为0,否则会产生浮点数例外,核心已转储,程序直接死掉
整数/整数,不会产生小数点 10/3=3 20/3=6
关系运算符: > < >= <= != ==
比较的结果是 1(真)或者 0(假),比较结果还能继续参与运算
10<n<100
== 建议:变量放右边,常量放左边
逻辑运算符: && || !
会把运算对象先转换为逻辑值,0转换假,非0都转换为真
A && B:一假即假
A || B:一真即真
!A : 求反
&&、||短路特性:当左边的值可以确定表达式的结果,那么右边就不计算了
三目运算符: 运算对象有三个部分
A?B:C
判断A是否为真,如果A为真,则执行B,如果A为假,则执行C
num = i == 0?99:100;
该语句不能使用流程控制语句,因为它必须要有运算结果
赋值运算符 := += -= *= /=
a+=b a=a+b
位运算符:& | ~ ^ >> <<
八、类型转换
自动类型转换:
只有相同类型的数据才能进行运算,不同类型的数据转换成相同类型再进行计算。
转换规则(以不丢失数据为基础,适当地牺牲一些空间)
1、字节少的向字节多的转
2、有符号向无符号转
3、整型向浮点型转
强制类型转换:
(类型)数据 有丢失数据的风险,慎用
九、条件分支
if(表达式)//单分支
{
表达式为真,则执行此处代码
}
if(表达式)//双分支
{
表达式为真,则执行此处代码
}
else
{
表达式为假,则执行此处代码
}
if(表达式1)//多分支
{
表达式1为真,则执行此处代码
}
else if(表达式2)
{
否则,表达式2为真,则执行此处代码
}
else if(表达式3)
{
否则,表达式3为真,则执行此处代码
}
else
{
1、2、3都不为真,则执行此处代码
}