一、第一个C程序:
#include<stdio.h>
//程序员所写的代码不是标准C代码,需要一段程序进行翻译成标准c代码,负责翻译的程序叫做预处理器,翻译的过程叫做预处理,被翻译的代码叫做预处理指令,以#开头的都是预处理指令;
// #include <xxx.h>:从系统指定的目录下加载xxx.h; #include"xxx.h ":先从当前目录下加载xxx.h,如果找不到再从系统的指定目录下加载xxx.h,适用于自己写的头文件;一般先加入(写)系统的头文件,再加入自己写的头文件;
// stdio.h:标准输入输出库函数
头文件:以.h结尾的文件,里面储存的是一些辅助性的代码,绝大多数都是函数的声明;
源文件:以.c结尾的文件,里面记录的是功能性代码;
C语言标准委员会为C语言以函数的形式提供了一些基础的功能,这些函数都会封装在libc.so库中
很多的头文件负责对libc.so库中的代码进行说明,stdio.h就是其中一个。
string.h stdlib.h
int main(){
// C语言以函数的形式来管理代码,是管理代码的最小单位,一个函数就是一个代码的集合;
main函数是C程序的主函数,是整个C程序的执行入口和出口,有且只有一个;
int 是一种数据类型,表示main函数的返回值类型是一个整数;
main函数的返回值返回给操作系统,main函数是由操作系统调用的,反映了该程序是如何结束的,通常有三种情况:
正数: 出现异常 (别人的错误)
0 :一切正常
负数: 出现错误 (自己的错误)
echo $? :获取上一个程序的返回值
printf(“hello world”\n);
//printf/scanf都是标准库中的函数,负责输入、输出数据,用来调试程序
段错误(使用了非法内存)
转义字符(\n):键盘是一些没有的符号,用一些特殊的字符来描述,这些特殊的字符就是转义字符,\n就是其中之一。
\n:换行 \t:制表符,TAB键 \r:回到行首 \a:响铃 \b:退一个字符 %%:表示一个% //:表示一个/
C语言中以 ;作为一行代码的结束标准。
return 0;
}
二、编译器
负责把人能看懂的代码文件,翻译成计算机能看懂的二进制文件,由预处理器、编译器,链接器组成
gcc是GNU社区为了编译Linux代码而开发的一块免费的编译器,默认采用C89语法标准, -std=gnu99 可以设置c99语法
常用的参数:
-E:显示预处理结果
-c:只编译不链接
-o:指定输出结果的名字
-I:指定头文件的加载路径
-S:生成汇编代码
-l(小写L):指定要使用的库文件
-Wall:尽可能多地产生警告
-Werror:把警告当做错误来处理(加在 -Wall后使用)
-std:指定编译语法
三、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.o b.o c.o…:默认生成一个a.out的可执行文件
四、C文件类型:
.h 头文件
.h.gch 头文件的编译结果,它会被优先使用
.c 源文件
.i 预处理文件
.s 汇编文件
.o 目标文件
.a 静态库文件
.so 共享库文件
五、数据的储存单位:
Bit 比特 一个二进制位,只能存0或者一个1,计算机就储存数据的最小单位
Byte 字节 八个二进制位,计算机中储存数据的基本单位
KB 1024个字节
MB 1024KB
GB 1024MB
TB 1024GB
六、数据类型:
为什么要对数据分类:
对数据分类可以节约储存空间,提高运行效率
C语言中数据分为两大类:自建(程序员自己设计,例如:结构、联合、类)、内建(C语言中自带)
内建:(可以用sizeof()计算类型的字节数大小)
整型(int):
signed:有符号
signed char : 字节 1 -128~127
signed short : 字节2 -32768~32767
signed int : 字节4 -21亿~21亿
signed long : 字节4\8 在32位系统中为4 8个字节是 ±以9开头的19位数字
signed long long :字节8
unsigned:无符号
unsigned char : 字节 1 0~255
unsigned short : 字节2 0~65535
unsigned int : 字节4 0~40亿
unsigned long : 字节4\8 在32位系统中为4
unsigned long long :字节8 1开头的20位数字
注意:由于定义无符号的数据比较麻烦,标准库把这些无符号的类 型重新定义成以下类型:(uint8_t uint16_t uint32_t uint64_t 无符号类型)(int8_t int16_t int32_t int64_t 有符号类型)需要导入<stdint.h>
浮点型(float):
float(单精度类型): 字节 4
double(双精度类型): 字节 8
long double(长精度类型) :字节12\16
注意:采用科学计数法储存,二进制与真实的数据之间需要翻译转换,因此浮点型运算速度就比整数要慢,编程时尽量采用整型,小数点后6位有效
布尔型(bool):由于先有的C语言后才有的bool类型,所以C语言不可能有真正的布尔类型,使用stdbool.h头文件,该文件是对布尔类型做的模拟(bool: true false)
字符型(char):其实就是符号或者图案,但是,在内存中储存的是整数,需要显示字符时,会根据ASCII码表中对应关系来显示相应的符号或者图案。
0 :‘’(特殊字符,表示什么都没有) 48 :‘0’(字符0) 65:‘A’ 97:‘a’
七、变量与常量
什么是变量:程序运行期间数值可以发生改变的叫做变量,相当于储存数据的盒子。
定义: 类型 变量名;
取名规则:
1.由字母、数字、下划线组成
2.不能以数字开头
3.不能与32个C关键字重名,能默写
4.见名知意(功能、类型、作用域。。。)
使用:
赋值:num = 100;
参与运算:num*10;
注意:C语言中变量的值是随机的,为了安全起见一般都初始化为0。
变量的输入、输出:
输出:
*int printf(const char format,…);
功能:输出数据
format:“双引号包含的格式信息(提示信息+占位符)”
…:要输出的变量的列表
返回值: 输出字符的个数
输入 :
*int scanf(const char format,…)
功能:从键盘输入数据
format:“双引号包括的格式信息(占位符)”
…:要接收的变量的列表
返回值:成功输入的变量的个数
注意:scanf需要的是变量的类型,变量等的地址,变量的地址 = &变量名
类型占位符:C语言通过占位符来传递变量的类型
signed: %hhd %hd %d %ld %lld
unsigned: %hhu %hu %u %lu %llu
浮点型: %f %lf %LF
什么是常量:程序运行期间数值绝对不能改变的叫常量
字面值常量:
100 ’a‘ “hello world”
枚举常量:
宏常量:
100:类型int | 100l:类型 long | 100u:类型unsigned int |3.14 :类型默认double | 3.14f :类型float
八、格式化输入输出
%nd :显示n个字符宽度,不够则补空格,右对齐
%-nd:显示n个字符宽度,不够则补空格,左对齐
%0nd:显示n个字符宽度,不够则补空格,右对齐
%n.mf:显示n个字符宽度,小数点也算一位,不够则补空格,m表示显示小数点后的位数(四舍五入)
%g :不显示小数点后面多余的0
九、运算符
自变运算符:前后++/–,使变量的值加一或者减一
前自变: 立即有效
后自变: 下一语句有效
注意:不要在一行语句中多次使用自变运算符
算术运算符:+ - * / %
/ % :除数不能为0,会造成浮点数例外,核心以转储,程序终结死掉
整数 / 整数 结果没有小数
关系运算符:> < >= <= == !=
比较的结果为0(假)或者1(真) if(a>b==0),运算结果可以继续参与运算
逻辑运算符:&& || !
比较的对象转换成逻辑值,0转换成假,非0转换为真
&&、||具有短路特性:当左边可以确定这个表达式的结果时不会再计算右边了
三目运算符:x>y?x:y;
注意:该语句不能使用流程控制语句,因为它必须要有运行结果
赋值运算符:= += -= *= /=
位运算符:& | ~ ^ g>> <<
十、类型转换
自动类型转换:
只有相同类型的数据才能进行运算,不同类型数据自动转换成相同类型再进行计算:
转换规则(以不丢失数据为基础(最基础),适当牺牲一些空间):
1.字节少的向字节多的转(最优)
2.有符号的向无符号的转(次)
3.整性向浮点型转换(最次)
强制类型转换:
(想要转成的类型)原来的数据:
int num;
(short) num;
注意:有丢失数据的风险,慎重使用;
十一、分支语句
1.单分支语句
if(表达式){
表达式为真,执行此处代码
}
2.双分支
if(表达式){
表达式为真,执行此处代码;
}else
{
表达式为假,执行此处代码
}
3.多分支
if(表达式1){
表达式1为真,执行此处代码;
}else if(表达式2)
{
表达式2为真,执行此处代码
}else if(表达式3)
{
…
}