第一个C语言程序:
#include<stdio.h>
程序员所写的代码不是标准的C代码,需要一段程序进行翻译成标准的C代码,负责翻译的程序叫做预处理,
翻译的过程叫做预处理,被翻译的代码叫做预处理指令,换句话说以#号开头的都是预处理指令。
#include<filename>
的功能就是把 后面的头文件导入当前的文件中 到相对应的位置直接复制拷贝到文件前面
#include< >
直接从系统指定的目录下 去查找是否有此头文件,有则导入 无则报错
#include" "
先从当先目录下寻找文件,例如key_board.h 再去系统找!
$path
打开系统路径
stdio.h
标准输入输出库函数
头文件:以 .h
结尾的文件都是头文件,储存是一些辅助性质的代码,绝大多数都是声明,函数声明
源文件:以 .c
结尾的文件,里面是功能性代码
C语言标准委员会,为C语言以函数形式提供了一些基础的功能,这些函数都会封装在一个libc.so
中
以 .so
结尾的为共享库
很多的头文件负责libc.so库中的代码进行说明,stdio.h就是其中的一个
例如 string.h stdlib.h iostream.h
int main()
C语言以函数的形式来管理代码,与数学上的函数完全不是一个东西,是处理事情的方法。一个函数就是
一段代码的集合
int 函数一般都需要返回值,int是它的返回值类型 类似人的尸检报告(函数死亡原因)
main() 函数的返回值返回给操作系统,main是由操作系统所调用的,反应了该程序是如何结束的,
通常有三种情况:
为什么要对数据进行分类:
1. 现实生活中的数据都是自带类别的属性
2. 对数据进行分类可以节约储存空间、还能提高运行的效率
echo $?
查看上一个程序的返回值
main() 是C程序的主函数,是整个程序的入口和出口,有且只有一个。
{
printf(“Hello World!\n”);
return 0;
}
自建类:程序员自己定义的类型 、例如:结构、联合、类
内建类:原本文件自带的类型
printf/scanf 都是标准库中的函数,复制输入,输出数据,可以调试代码。
段错误:内存错误,非法使用内存 类似数组越界 无法具体查到哪一行出现了错误
转义字符:无法打出的符号
\n 换行 \t TAB \r 回到行首(打印出来可能会被覆盖,长一点) \a 铃响(古老的东西)
\b 退一个字符 %% 表示% \\ 表示\ \t 一般用于对齐数据
;分号 在C语言中代表语句的结束,默认下一行
{} 大括号 使用大括号分隔区域
编译器
把人能看懂的代码文件,翻译成计算机能看懂的01010101,二进制文件。由于处理器,
编译器,链接器组成
gcc 是GNU社区为了编译Linux代码而开发的一款免费的编译器,默认采用C89标准,
常用参数
-std=gnu99 可以设置 C99语法
-E 显示预处理的结果
-c 只编译不链接
-o 指定输出结果的名字 换句话说 改变a.out的名字 gcc a.c -o hello
-I 指定头文件的加载路径
-S 进行汇编,生成生成代码
-l(小写L)指定要使用的库文件
-Wall 尽可能多的产生警告 让代码更加严谨 会提示很多警告,
-Werror 把警告-》错误处理
-std 指定编译语法
C代码变成可执行程序的过程
1. 预处理:把源文件翻译成标准c代码,翻译成所谓的预处理文件
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 -o code.o code1.o code2.o....
-----> code.out 默认生成一个 以 .out
结尾的可执行文件
C语言以各种不同结尾的文件类型
.h 头文件
.h.gch 头文件的编译结果,它会被优先使用
.c 源文件
.i 预处理文件
.s 汇编文件 .S(新的)
.o 目标文件
.a 静态库文件
.so 共享库文件
.out 可执行文件
数据的储存单位
Bit或者b 比特 一个0 或者 一个1 、一个二进制位、计算机中储存数据的最小单位
Byte或者B 1字节 = 8 Bit 等于八个二进制位 、计算机中储存的基本单位
KB 1KB = 1024 Byte
M 1M = 1024KB
GB 1G = 1024M
TB 1T = 1024G
数据类型
可以使用sizeof计算类型的字节数大小 sizeof
整型(定典型):
signed:有符号的整型
只能是正数 范围并不是一段、而是一个环
signed char 一个字节1B -128~127
signed short 两个字节2B -32768~32767
signed int 四个字节4B 正负20亿
signed long 四个或者八个字节,取决于操作系统的位数32或者64 以9开头的19位整数
signed long long 八个字节
注意 默认signed不显示,可以不加*
unsigned:无符号的整型
unsigned char 一个字节1B 0~255
unsigned short 两个字节2B 0~65535
unsigned int 四个字节4B 0~40亿
sunigned long 四个或者八个字节,取决于操作系统的位数32或者64 0~1开头的20位正整数
unsigned long long 八个字节
注意*为了定义无符号的数据时比较麻烦,标准库把这些无符号的类型重新定义一下,也叫类型重定义
换句话说大名和小名的意思 指代同一个东西、定义成以下的类型:
需要包含一个头文件<stdint.h>
无符号的:uint8_t uint16_t unit32_t unit64_t (数字代表有多少位,来匹配对应
有符号的:int8_t int16_t int32_t int6
浮点型:
float 四个字节 表示精度
double 八个字节
long double 十二个或者十六个,还是取决于操作系统
采用科学计数法储存,二进制与真实的数据之间需要翻译转换,因此浮点型的运算速度就比整数速度慢很多
编程时,能少用就少用。
time ./a.out 可以输出a.out的运行时间
float 小数点后六位有效 0.0000001
判断float类型的数据是否为0
float num;
if(num 0 <= 0.0000001 || num >= -0.0000001)
模拟
字符型:
char 字符型其实就是符号或者是图案,但是在内存中只能是整数,需要显示字符时,会根据ASCII码表中对应
关系相应的符号或者图案。
0 ‘’ 特殊字符,表示什么都没有
48 ’0’
65 ‘A’
97 ‘a’
布尔型:bool
由于先有的C语言,才有了bool类型,所以C语言不可能有真正的布尔类型,
使用stdbool.h的头文件,该文件是对布尔类型做的模拟。
bool true false
变量和常量
什么是变量:
程序运行期间数值可以发生改变的叫做变量,相当于储存数据的盒子。
定义: 类型 变量名;
int num;
取名规则:
1. 由字母、数字、下划线组成
2. 不能以数字作为开头
3. 不能与32个关键字重名
4. 见名知意 —功能—类型—作用域—
例如 printf scanf bool sizeof 是否能成为变量名? 按照上面的几个规则判断,但是不能和函数同时使用
数据类型:
内建类型:
void char short int long float double 7
自建类型:
struct union enum sizeof 4
类型限定符:
auto const static volatile reggister extern typedef signed unsigned 9
流程控制相关:
分支:
if else switch case default 5
循环:
do for while 3
跳转:
break countinue goto return 4
数据使用:
赋值: num = 100;
参与运算:num*10;
注意:在C语言中变量值默认是随机的,为了防止踩坑,记得初始化,在定义的时候给才是,后面给是赋值
变量输出:
int printf(const char *format, ...);
功能:输出数据
format:“双引号包含的格式信息(提示信息+占位符+)”
… : 长度可变,是变量的列表由占位符决定
返回值:输出字符的个数 ’\n‘ 也算一个
set = 100;
int a = printf("%d\n",set);
a = 4;
int scanf(const char *format,...);
功能:从键盘输入数据
format:“双引号包括的格式信息(占位符)”
scanf(“%d %d”)
—意味着输入一个 打一个空格 再输入 不然应该 scanf(“%d%d”)
… :要接收的变量的列表
返回值:成功输入变量的个数 —用于判定是否输入成功
注意:scanf需要的是变量的类型、变量的地址、变量的地址=&变量名;
练习1:定义各种类型的变量并初始化,使用scanf输入,使用printf显示
类型占位符:
C语言通过占位符来传递变量的类型
signed: %hhd %hd %d %ld %lld
unsigned: %hhu %hu %u %lu %llu
浮点型:%f %lf %LF
什么是常量:
程序运行期间数值绝对不能改变的叫常量
字面值常量
100 ’a‘ “hello world”
枚举常量
宏常量
100 默认是有符号的int类型
100u unsigned int
100l long
100ll long long
100lu unsigned long
100llu unsigned longlong
3.14 默认double
3.14f float
格式化输入输出:
%d 默认
%nd 显示n个字符宽度,换句话说右对齐
%-nd 左对齐
%0nd 前面添加一个0 例如在12:05 时间中较为常用
%nf 显示n个字符宽度、小数点算一位,整数有几位算几位 例如:3.14—3.140000—%9lf—才会补空格
%n.mf 显示n个字符宽度,保留小数点后m位,会自动四舍五入
%g 不显示小数点后面多余的0
运算符
自变运算符: 前后++/-- 使变量的值自动加1或者减1
前自变: 立即有效 无论其余语句先加一
后自变: 下一句有效
例如
int num = 100;
num = num++ + ++num;
num = 23!
注意*不要在一行语句中 超过两次以上++语句,很复杂。
算术运算符
+ - * / %
除数不能为0 会出现 浮点型例外 - 核心已转储 的错误,程序会死掉
整数/整数 结果没有小数部分
关系运算符:
< > <= >= == !=
比较的结果是0false 或者是 1true
int num = 500;
0<num<100; 数学上为真,但是实际上是先判断0<500为真—1<100—所以永远为真
逻辑运算符:
&& || !
比较对象转换为逻辑值,0转换为假,1转换为真
! 求返
&& || 具有短路特性:当左边表达式符合要求后,就不再计算右边的
三目运算符:
三个运算对象!有三个部分
A?B:C 判断A的表达式真假,如果为真执行B,如果为假执行C
注意*该语句不能使用流程控制语句,因为它必须要有运行结果
int a = 0 == 1?100:1000;
a = 1000;
赋值运算符:= += -= *= /=
位运算符:& | ~取反 ^异或 >>右移 <<左移
类型转换
自动转换类型:
只有相同类型的数据才能进行运算,不同类型数据自动转换成相同类型再进行计算!
以不丢失数据为基础,可以适当的牺牲一些空间
1. 字节少的向字节多的转 考虑规则
2. 有符号向无符号的转
3. 有整型向浮点型转
强制类型转换:
(想要转成的类型) 原来的数据 变量名;
int num;
(short)num;
有丢失数据的风险、慎重使用!
分支语句
if(表达式) 单分支
{
如果表达式的值为真,执行此处代码;
}
if(表达式) 双分支
{
如果表达式的值为真,执行此处代码
}else
{
如果表达式的值为真,执行此处代码
}
else if n分支…