目录
一、C语言课程规划
1.c程序的基本组成 2.c的函数入口 头文件
3.变量和常量 4.标识符和关键字
5.运算符 6.分支语句
7.循环语句 8.函数和预处理指令
9.数组 10.指针
11.函数数组指针的高级用法 12.复合类型:结构体 共用体
13.文件操作:标准io(apue)
二、C语言的开发环境
Linux C-->ubuntu
编辑-->vim
编译器-->gcc
三、gcc编译过程
四个步骤:
1. 预处理: -E 将文件中所有#开头的指令,做相应处理,例如#include,gcc会将包含的文件找到并展开到文件中
2. 编译: -S 将c程序,翻译成汇编指令
3. 汇编: -c 执行汇编动作,将汇编指令执行并生成机器码
4. 链接:-o 一般c程序都不能独立执行,都需要再执行期间加载库文件,例如我们使用的printf函数就是c标准库提供的接口,gcc会在链接的阶段记录库文件的地址。最终生成可执行文件
生成目标文件的命令: (例子) gcc -o hello hello.c 或 make hello
四、变量和常量
变量:数值可变的,需要申请存储空间,容纳可变的数值,申请存储空间就需要定义变量
类型决定存储空间大小和运算能力
空间大小单位:数据类型所占存储空间大小与编译器息息相关的
计算机是按位存储的 bit 8bit == 1byte
字符型 char(1byte)
整型 short(2bytes) int(4 bytes) long(8bytes) (long long 8bytes)
实型 float(4bytes) double(8bytes) long double (16bytes)
空类型 void
变量是可以有符号的
int a; 定义了一个有符号的整型变量a,signed可省略
unsigned int a; a就是无符号的整型变量
对于有符号的变量,对应二进制的最高位表示符号位 0正数 1负数
变量的存储
在计算机中,数值都是使用补码方式存储的
正数的原码 反码 补码都一样
负数的补码==原码-->反码+1
反码就是将原码按位取反,符号位不变的
变量名是c语言标识符一种
五、输出和读入
1. %d int类型变量的格式占位符 2. %c char类型
3. %ld long类型 4. %hd short类型
5. %x 十六进制输出 6. %o 八进制输出
7. %s 字符串 8. %p 地址(十六进制)
.....更多的参考手册man 3 printf
%3d 输出的整型变量占3个字符宽度的,不够补空格, 靠右对齐
%-3d 输出的整型变量占3个字符宽度的,不够补空格,靠左对齐
读入 scanf();
按照指定格式读入
scanf("%d", &n);读入一个整型变量, 将读取的整型变量存储到n对应的地址空间中
scanf("%d%d", &m, &n); 两个整型变量间用空格或者换行区分
scanf("%d,%d", &m, &n); 输入的时候必须有,
scnaf("请输入%d", &n);你想多了!!!!!!!请输入没有任何价值,你还要写请输入。不推荐。
六、运算符和表达式
man operator
单目运算符:只有一个操作数
() 括号运算符,优先级最高的
[] 取值运算符
-> 成员运算符(指针)
. 成员运算符
sizeof 存储空间大小运算符
& 取地址运算符
* 取值运算符,类似于[]
(type) 类型转换运算符
+ - 正负
++ -- 自增 自减运算符
算数运算符
+ - * / %(模运算,求余数)
位运算符
>>(低位移出,高位补符号位(正数补0 负数补1))
&(按位做与运算,只有同时为1结果才是1)
|(按位或,只要有1位是1结果就是1)
~(按位取反,0取反就是1,1取反就是0)
^(按位异或,相同为0,不同为1)
要清除位运算,前提学会进制间转换
十进制转二进制
凑数法:用2的n次方凑数, 2^0 2^1 2^2.... 2^10
例如十进制100
100 == 64 + 32 + 4 == 2 ^ 6 + 2^5 + 2^2 == 1100100
对2求余数,直到除尽,结果就是所得余数的倒序
八进制转二进制
八进制就是逢八进一:0~7
每一位八进制数对应三位的二进制
例如0724== 111 010 100
十六进制转二进制
十六进制:0~9 a~f
每一位十六进制数对应四位二进制数
例如0x3f 0011 1111
二进制转十进制
凑数法: 10110011==2^7 + 2^5 + 2^4 + 2^1 + 2^0 == 128 + 32 + 16 + 2 + 1 == 179
二进制转八进制
每三位的二进制对应一位八进制
例如:10110011==0263
二进制转十六进制
每四位的二进制对应一位的十六进制
例如:10110011==0xb3
将a的第三位置1,其他位不变
a | 1u
将a的第八位清0,其他位不变
a & ~(1u
关系运算符
== != > < >=
不能连续,如果表达在1~100之间, n >= 1 && n
逻辑运算符
&& 逻辑与 运算符两侧的表达式同时为真,结果才是真,如果左侧的表达式为假,右侧表达式就不会执行了
|| 逻辑或 运算符两侧的表达式只要有一侧为真,结果就是真,如果左侧的表达式为真,右侧表达式就不会执行了
! 逻辑取反 真取反为假,假取反为真
条件运算符
表达式1?表达式2:表达式3;表达式1为真吗,如果为真整个表达式的结果就是表达式2,如果为假整个表达式的结果就是表达式3
赋值运算符
= += -= *= /= .....
赋值运算时自右向左
逗号运算符
, 运算自左向右,依次执行每一个表达式,左右一个表达式时整个逗号运算的结果
七、原码、反码、补码
1)取反
1.正数的原码、反码、补码都一样
2.无论什么时候,一个正数取反的结果都是这个数加一,然后在这个数前面加一个负号。例如:~8==-9 ~21==-22
一个负数取反的结果都是这个数的绝对值减一,然后在这个数前面加一个负号。 ~-3==2
3.运算过程:
以~-6为例:
-6的原码:1000 0110 -6的反码:1111 1001 -6的补码:1111 1010 0000 0101
-6的原码先转为反码,(符号位不变,其余位置取反),然后加1,成为补码。此时,将这个-6的补码进行各个位置取反,就是所得的结果:0000 0101,也就是5
以~9为例:
9的原码:0000 1001 9的反码:0000 1001 9的补码:0000 1001 1111 0110 1000 1001 1000 1010
9的原码反码补码都一样,都为0000 1001,此时各个位置取反,获得补码1111 0110,然后除符号位外其余各位取反获得反码1000 1001,然后加1获得最终结果1000 1010也就是-10
由以上结果总结:
求一个数的反码:
无论这个数是正数还是负数,先求出这个数的补码,然后将该数取反(各个位置都取反,符号位也不例外)
1.若原数为正数,将取反后的数除符号位外,其余各位再次取反,然后加1,获得最终结果
2.若原数为负数,已经得到最终结果
2)左移、右移
一般情况下,左移一位是将原来的数*2,左移两位是将原来的数*4,右移一位是将原来的数/2,右移一位是将原来的数/4
例如:-1 >> 1 (-1右移一位)
-1原码 1000 0001 反码 1111 1110 补码 1111 1111
通过-1的原码,求出-1的补码1111 1111,然后开始右移,低位移出,高位补符号位数字,因此,右移一位之后的二进制数仍为1111 1111,即为-1
-8 >> 1 (-8右移一位)
-8原码 1000 1000 反码 1111 0111 补码 1111 1000
通过-8的原码,求出-8的补码1111 1000,然后右移一位,低位移出,高位补符号位数字,因此,右移一位之后的二进制数 1111 1100,将补码1111 1100取反,得1000 0011,然后加1,得到原码1000 0100,即为-4
5 >> 1 (5右移一位)
5原码 0000 0101 反码 0000 0101 补码 0000 0101
将5的补码进行右移一位,低位移出,高位补符号位数字,为0000 0010,数字为2