Makefile使用:
TAR = test
CC = gcc
OBJ = *.o

#$^所有的依赖文件, #$@所有目标文件
$(TAR):$(OBJ)
$(CC) $^ -o $@

#%.c任意的.c , $.o任意的.o
%.o:%.c
$(CC) -c $^ -o $@

clean:
rm -rf $(OBJ)
cleanall:
rm -rf $(OBJ) $(TAR)




gcc使用
gcc工作原理
预处理gcc -E
编译 gcc -S
汇编 gcc -c
链接 gcc 无参数

预处理:gcc -E hello.c -o hello.i
编译: gcc -S hello.i -o hello.s
汇编: gcc -c hello.s hello.o
链接: gcc hello.o -o helo

gcc c源文件.c -o 生成可执行文件名称
不指定可执行文件名称默认生产a.out

gcc编译时指定 -I头文件位置(头文件在可执行文件目录中不需要指定位置)

-D 指定宏位置

-O1默认优化 -O3最高级优化
...
静态库
命名规则 lib+库名字+.a

制作静态库步骤
生成.o文件
gcc c源文件 -c

打包.o文件
ar rcs lib静态库文件名字.a + 上一步生成的.o文件

发布
给客户 静态库文件和头文件两部分

客户拿到静态库和头文件后,可以自己再写个c程序来调用静态库和头文件里面的函数,
然后再gcc可执行文件发布出去,发布出去不用再给别人前面的静态库和头文件了(这是优点),
因为在生成可执行文件就打包进去了。所以静态库缺点就是容量大,
如果库文件或者头文件发生改变,要重新生成可执行文件,比较麻烦。

...
动态库(共享库)
命名规则 lib+库名字+.so

制作动态库步骤
生成.o文件
gcc c源文件 -fPIC -c

打包.o文件
gcc -shared -o lib静态库文件名字.so + 上一步生成的.o文件

客户拿到动态库和头文件后,可以自己再写个c程序,用动态库连接器调用(ldd + 可执行文件 可查看,最后一排就是动态库连接器ld.so.conf,其实也是一个库文件在/etc下,
一般都是把自己写的动态库位置文件夹路径,写到这个文件里面,
然后再更新系统库文件ldconfig -v,
不然客户发布的可执行文件找不到库报错)动态库和头文件里面的函数,
然后再gcc可执行文件发布出去



#define MAX 100 //常量

const int b = 10; //只读常量

sizeof(a)查看a变量的空间多大


#include <stdio.h>
#include <stdlib.h>

int main()
{
//system("calc"); //windows平台
system("ls"); //Linux平台, 需要头文件#include <stdlib.h>

return 0;
}

linux 可以通过man 3 printf查看printf所需的头文件,其它一样的查

ldd hello 查自己写的可执行文件依赖的头文件

#include <stdio.h>

int main()
{
int a;
printf("请输入a的值:");

//不要加“\n”
scanf("%d", &a);

printf("a = %d\n", a); //打印a的值

return 0;
}

数据类型 占用空间
short(短整型) 2字节
int(整型) 4字节
long(长整形) Windows为4字节,Linux为4字节(32位),8字节(64位)
long long(长长整形) 8字节


打印格式 含义
%hd 输出short类型
%d 输出int类型
%l 输出long类型
%ll 输出long long类型
%hu 输出unsigned short无符号类型
%u 输出unsigned int无符号类型
%lu 输出unsigned long无符号类型
%llu 输出unsigned long long无符号类型

2.6.2 字符变量的输入
#include <stdio.h>

int main()
{
char ch;
printf("请输入ch的值:");

//不要加“\n”
scanf("%c", &ch);
printf("ch = %c\n", ch); //打印ch的字符

return 0;
}

数据类型 占用空间 有效数字范围
float 4字节 7位有效数字
double 8字节 15~16位有效数字

#include <stdio.h>

int main()
{
//传统方式赋值
float a = 3.14f; //或3.14F
double b = 3.14;

printf("a = %f\n", a);
printf("b = %lf\n", b);

//科学法赋值
a = 3.2e3f; //3.2*1000 = 32000,e可以写E
printf("a1 = %f\n", a);

a = 100e-3f; //100*0.001 = 0.1
printf("a2 = %f\n", a);

a = 3.1415926f;
printf("a3 = %f\n", a); //结果为3.141593

return 0;
}



8进制一位对应二进制三位
例: 111 110
7 6

16进制一位对应二进制四位
例:1110 1111
E F


2.5.4 有符号数和无符号数区别

先要了解:原码、反码、补码都是为了解决计算机计算负数的问题:

1、0开头的是正数(无符号数),1开头的负数(有符号数)。
(例10111 0001,第一个数标示是正数还是负数)

2、电脑上显示的:正数开头的显示的十六进制、八进制、二进制都是可以直接转为10进制的数
例:01110 0001 第一个0为标示不在计算范围内,直接把1110 0001转成10进制就可以了。

3、电脑上显示的:负数开头的显示的十六进制、八进制、二进制都是补码,要先转成反码,
再转原码才可以进行10进制转换。
例:11110 1111 第一个1为标示不在计算范围内,先把1110 1111补码转成反码,再反码转
成原码,再转成10进制。

4、原码转反码(取反0换成1,1换成0),反码转补码(反码加1)

5、补码转反码(取反0换成1,1换成0),反码转原码(反码加1)

打印格式 含义
%hd 输出short类型
%d 输出int类型
%l 输出long类型
%ll 输出long long类型
%hu 输出unsigned short类型
%u 输出unsigned int类型
%lu 输出unsigned long类型
%llu 输出unsigned long long类型

1) 有符号数
有符号数是最高位为符号位,0代表正数,1代表负数。

有符号位的先把补码转反码再转原码才能进行对二进制转十进制计算
#include <stdio.h>

int main()
{
signed int a = -1089474374; //定义有符号整型变量a
printf("%X\n", a); //结果为 BF0FF0BA

//B F 0 F F 0 B A
//1011 1111 0000 1111 1111 0000 1011 1010

return 0;
}

2) 无符号数
无符号数最高位不是符号位,而就是数的一部分,无符号数不可能是负数
#include <stdio.h>

int main()
{
unsigned int a = 3236958022; //定义无符号整型变量a
printf("%X\n", a); //结果为 C0F00F46

return 0;
}

2.5整型:int
2.5.1 整型变量的定义和输出
打印格式 含义
%d 输出一个有符号的10进制int类型
%o(字母o) 输出8进制的int类型
%x 输出16进制的int类型,字母以小写输出
%X 输出16进制的int类型,字母以大写写输出
%u 输出一个10进制的无符号数

#include <stdio.h>

int main()
{
int a = 123; //定义变量a,以10进制方式赋值为123
int b = 0567; //定义变量b,以8进制方式赋值为0567
int c = 0xabc; //定义变量c,以16进制方式赋值为0xabc

printf("a = %d\n", a);
printf("8进制:b = %o\n", b);
printf("10进制:b = %d\n", b);
printf("16进制:c = %x\n", c);
printf("16进制:c = %X\n", c);
printf("10进制:c = %d\n", c);

unsigned int d = 0xffffffff; //定义无符号int变量d,以16进制方式赋值
printf("有符号方式打印:d = %d\n", d);
printf("无符号方式打印:d = %u\n", d);
return 0;
}

2.6.3 转义字符
转义字符 含义 ASCII码值(十进制)
\a 警报 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\\ 代表一个反斜线字符"\" 092
\' 代表一个单引号(撇号)字符 039
\" 代表一个双引号字符 034
\? 代表一个问号 063
\0 数字0 000
\ddd 8进制转义字符,d范围0~7 3位8进制
\xhh 16进制转义字符,h范围0~9,a~f,A~F 3位16进制

字符串常量与字符常量的不同:


每个字符串的结尾,编译器会自动的添加一个结束标志位'\0',即 "a"
包含两个字符'a'和’\0’。
打印格式 对应数据类型 含义
%d int 接受整数值并将它表示为有符号的十进制整数
%hd short int 短整数
%hu unsigned short 无符号短整数
%o unsigned int 无符号8进制整数
%u unsigned int 无符号10进制整数
%x,%X unsigned int 无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF
%f float 单精度浮点数
%lf double 双精度浮点数
%e,%E double 科学计数法表示的数,此处"e"的大小写代表在输出时用的"e"的大小写
%c char 字符型。可以把输入的数字按照ASCII码相应转换为对应的字符
%s char * 字符串。输出字符串中的字符直至字符串中的空字符(字符串以'\0‘结尾,这个'\0'即空字符)
%p void * 以16进制形式输出指针
%% 输出一个百分号

* 乘 10 * 5 50
/ 除 10 / 5 2
% 取模(取余) 10 % 3 1
++ 前自增 a=2; b=++a; a=3; b=3;
++ 后自增 a=2; b=a++; a=3; b=2;
-- 前自减 a=2; b=--a; a=1; b=1;
-- 后自减 a=2; b=a--; a=1; b=2;

3.3 赋值运算符
运算符 术语 示例 结果
= 赋值 a=2; b=3; a=2; b=3;
+= 加等于 a=0; a+=2; a=2;
-= 减等于 a=5; a-=3; a=2;
*= 乘等于 a=2; a*=2; a=4;
/= 除等于 a=4; a/=2; a=2;
%= 模等于 a=3; a%2; a=1;



3.4 比较运算符
C 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示。
运算符 术语 示例 结果
== 相等于 4 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0
> 大于 4 > 3 1
<= 小于等于 4 <= 3 0
>= 大于等于 4 >= 1 1

3.5 逻辑运算符
运算符 术语 示例 结果
! 非 !a 如果a为假,则!a为真;
如果a为真,则!a为假。
&& 与 a && b 如果a和b都为真,则结果为真,否则为假。
|| 或 a || b 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。

3.6 运算符优先级
优先级 运算符 名称或含义 使用形式 结合方向 说明
1 [] 数组下标 数组名[常量表达式] 左到右 --
() 圆括号 (表达式)/函数名(形参表) --
. 成员选择(对象) 对象.成员名 --
-> 成员选择(指针) 对象指针->成员名 --

2 - 负号运算符 -表达式 右到左 单目运算符
~ 按位取反运算符 ~表达式
++ 自增运算符 ++变量名/变量名++
-- 自减运算符 --变量名/变量名--
* 取值运算符 *指针变量
& 取地址运算符 &变量名
! 逻辑非运算符 !表达式
(类型) 强制类型转换 (数据类型)表达式 --
sizeof 长度运算符 sizeof(表达式) --

3 / 除 表达式/表达式 左到右 双目运算符
* 乘 表达式*表达式
% 余数(取模) 整型表达式%整型表达式
4 + 加 表达式+表达式 左到右 双目运算符
- 减 表达式-表达式
5 << 左移 变量<<表达式 左到右 双目运算符
>> 右移 变量>>表达式

6 > 大于 表达式>表达式 左到右 双目运算符
>= 大于等于 表达式>=表达式
< 小于 表达式<表达式
<= 小于等于 表达式<=表达式
7 == 等于 表达式==表达式 左到右 双目运算符
!= 不等于 表达式!= 表达式

8 & 按位与 表达式&表达式 左到右 双目运算符
9 ^ 按位异或 表达式^表达式 左到右 双目运算符
10 | 按位或 表达式|表达式 左到右 双目运算符
11 && 逻辑与 表达式&&表达式 左到右 双目运算符
12 || 逻辑或 表达式||表达式 左到右 双目运算符

13 ?: 条件运算符 表达式1?
表达式2: 表达式3 右到左 三目运算符

14 = 赋值运算符 变量=表达式 右到左 --
/= 除后赋值 变量/=表达式 --
*= 乘后赋值 变量*=表达式 --
%= 取模后赋值 变量%=表达式 --
+= 加后赋值 变量+=表达式 --
-= 减后赋值 变量-=表达式 --
<<= 左移后赋值 变量<<=表达式 --
>>= 右移后赋值 变量>>=表达式 --
&= 按位与后赋值 变量&=表达式 --
^= 按位异或后赋值 变量^=表达式 --
|= 按位或后赋值 变量|=表达式 --

15 , 逗号运算符 表达式,表达式,… 左到右 --

数据类型转换:
3.7.1 隐式转换
#include <stdio.h>

int main()
{
int num = 5;
printf("s1=%d\n", num / 2);
printf("s2=%lf\n", num / 2.0);

return 0;
}
3.7.2 强制转换
强制类型转换指的是使用强制类型转换运算符,将一个变量或表达式转化成所需的类型,
其基本语法格式如下所示:
(类型说明符) (表达式)

#include <stdio.h>

int main()
{
float x = 0;
int i = 0;
x = 3.6f;

i = x; //x为实型, i为整型,直接赋值会有警告
i = (int)x; //使用强制类型转换

printf("x=%f, i=%d\n", x, i);

return 0;
}


if语句使用:
#include <stdio.h>

int main()
{
unsigned int a;
scanf("%u", &a);

if (a < 10)
{
printf("个位\n");
}
else if (a < 100)
{
printf("十位\n");
}
else if (a < 1000)
{
printf("百位\n");
}
else
{
printf("很大\n");
}

return 0;
}

4.2.4 三目运算符
#include <stdio.h>

int main()
{
int a = 10;
int b = 20;
int c;

if (a > b)
{
c = a;
}
else
{
c = b;
}
printf("c1 = %d\n", c);

a = 1;
b = 2;
c = ( a > b ? a : b );
printf("c2 = %d\n", c);

return 0;
}


4.2.5 switch语句
#include <stdio.h>

int main()
{
char c;
c = getchar();

switch (c) //参数只能是整型变量
{
case '1':
printf("OK\n");
break;//switch遇到break就中断了
case '2':
printf("not OK\n");
break;
default://如果上面的条件都不满足,那么执行default
printf("are u ok?\n");
}
return 0;
}


while 语句
#include <stdio.h>

int main()
{
int a = 20;
while (a > 10)
{
scanf("%d", &a);
printf("a = %d\n", a);
}

return 0;
}

do while语句

#include <stdio.h>

int main()
{
int a = 1;
do
{
a++;
printf("a = %d\n", a);
} while (a < 10);

return 0;
}

4.3.3 for语句
#include <stdio.h>

int main()
{
int i;
int sum = 0;
for (i = 0; i <= 100; i++)
{
sum += i;

}

printf("sum = %d\n", sum);

return 0;
}


4.3.3 goto语句(无条件跳转,尽量少用)
#include <stdio.h>

int main()
{
goto End; //无条件跳转到End的标识
printf("aaaaaaaaa\n");

End:
printf("bbbbbbbb\n");