学习C(二)
缓冲区GCC编译过程硬链接和软链接getchar()函数define()函数、typedef()函数计算机中二进制的计算(补码的计算)计算类型的最大值
缓冲区
scanf函数和printf函数一样,拥有缓存区: 在终端上输入的数据,并不会直接写入变量中,而是先会写到缓存去中,当遇到回车,再从缓存区写入格式占位符中,最后再从格式占位符写入变量。如果格式占位符与缓存区中第一个数据类型不匹配,则直接跳过接收过程。 所以,无论如何使用scanf,为了结束输入,总是需要输入回车,导致缓存区总是会以回车结尾。 这样就会影响到下一次scanf的使用。所以我们每一次的scanf过后,都需要清理一下缓存: 缓存清理的代码:while(getchar()!='\n'); 例子1:scanf缓存区
#include<stdio.h>
int main(){
int num
= 5;
char ch
= 0;
scanf("%d",&num
);
printf("num = %d\n",num
);
scanf("%c",&ch
);
printf("ch = %c\n",ch
);
scanf("%c",&ch
);
printf("ch = %c\n",ch
);
scanf("%c",&ch
);
printf("ch = %c\n",ch
);
scanf("%d",&num
);
printf("num = %d\n",num
);
return 0;
}
当输入123\n4567\n时,输出的结果如下: 分析如下:
缓存区123\n4567\n
–scanf("%d",&num);scanf("%c",&ch);scanf("%c",&ch);scanf("%c",&ch);scanf("%d",&num);scanf()num接收123ch接收\nch接收4ch接收5num接收67输出num=123ch=\nch=4ch=5num=67
此时缓存区还剩下\n
例子2:scanf缓存清理
#include<stdio.h>
int main(){
int num
= 5;
char ch
= 0;
scanf("%d",&num
);
while(getchar()!='\n');
printf("num = %d\n",num
);
scanf("%c",&ch
);
while(getchar()!='\n');
printf("ch = %c\n",ch
);
scanf("%c",&ch
);
while(getchar()!='\n');
printf("ch = %c\n",ch
);
return 0;
}
当输入123\n4567\n89时(\n代表回车),输出的结果如下: 分析如下:
缓存区1234567\n89\n
–scanf("%d",&num);scanf("%c",&ch);scanf("%c",&ch);–while(getchar()!=’\n’);while(getchar()!=’\n’);while(getchar()!=’\n’);scanf()num接收123,\n被清理ch接收4,567\n被清理ch接收8,9\n被清理输出num=123ch=4 其中ch=8
此时缓存区为空
GCC编译过程
gcc编译的具体流程: gcc 编译过程一共分为4个流程:例如现在想要编译的文件名为demo.c ①:预处理阶段 gcc -E demo.c -o demo.i gcc的参数: -E:代表只做预处理,其他都不做 -o:指定输出文件的名字 1:头文件的展开 头文件:该文件中存放了各种库函数的函数声明(头文件中仅仅有函数声明,函数的定义在其他地方) 2:简单宏替换(傻瓜式替换) 什么是宏:使用#define 将一个名字 声明成 一个数据 什么是带参宏:使用#define 将一个带参数的名 声明成 与该参数有关的数学表达式 所有的宏,全都使用大写表示 注意区别#define和typedef typedef:将一个数据类型,取一个别名 例如:typedef int OI #define OI int 无论是#define还是typedef,都会使用最后一个数据参与编译(也就是说,#define参与编译的对象是int,typedef参与编译的对象是OI)。在typedef当中,编译器会将OI认定成int进行编译 3:去注释 注释:“//”代表行注释,在“//”之后一整后内容都为注释内容 一组“/” 代表多行注释,写在“/”两个*号内部的内容都为注释 4:上标记:为每一行代码,标记上准确的源文件中的行号 预处理完成之后,生成了预处理文件。注意,预处理仅仅做以上4步,如果程序语法有任何问题,预处理阶段不会做任何干涉 ②:编译阶段:gcc -S demo.i -o demo.s 对预处理文件进行词义,语义及语法分析。当所有语法都正确的情况下,将预处理文件,编译成汇编文件。编译阶段是整个gcc过程中最重要的阶段 ③:汇编阶段:gcc -c demo.s -o demo.o 将汇编文件,转换成计算机能够识别的二进制文件 ④:链接阶段:gcc demo.o -o demo 将二进制文件追加可执行权限,并且转换成可执行文件的格式 并且链接动态库与静态库(仅仅链接动态库与静态库,其他的各种函数库不会默认链接,如果需要使用,注意使用参数 -l+函数库名 去链接函数库) 动态库与静态库中包含了绝大多数的库函数的定义 链接阶段完成后,生成名叫demo的可执行文件
硬链接和软链接
硬链接和软链接: 使用shell ln+源文件名+链接文件名,会为源文件创建一个链接文件,并且名字为链接文件名。 此时,创建出来的链接文件属于硬链接,硬链接是一个普通文件 那么如何创建一个真正的链接文件:使用ln -s参数创建一个软连接 硬链接:他拥有一份源文件的拷贝以及连接到源文件的链接 软链接:他只拥有连接到源文件的链接 当源文件发生改变,硬链接和软链接因为都拥有连接到源文件的链接,所有都会发生改变 当源文件删除时,因为硬链接拥有源文件的拷贝,所以访问硬链接不受影响 但是,软链接只有连接到源文件的链接,所以,软链接无法访问
getchar()函数
#include<stdio.h>
int main(){
char ch
= getchar();
printf("%c\n",ch
);
return 0;
}
getchar()函数只读取一个字符,即使输入很多个字符也是只读取一个字符,剩下的留在缓存区
define()函数、typedef()函数
#include<stdio.h>
#include<pthread.h>
#define PI (3+3)
#define F(n) ((n)*(n))
#define OOI int
typedef int OI
;
int main(){
int a
= 5;
OI b
= 5;
printf("%d\n",a
);
printf("%d\n",b
);
return 0;
}
计算机中二进制的计算(补码的计算)
10+6=16
源码反码补码
100000 1010 ->->0000 101060000 0110->->0000 0110160001 0000<-<- 0001 0000
10-6=4 即10+(-6)=4 负数补码:源码符号位不变,其余求反加1。即反码加1。
源码反码补码
100000 1010 ->->0000 1010-61000 0110 ->1111 1001 ->1111 101040000 0100<-<- 0000 0100
6-10=-4即6+(-10)=-4
源码反码补码
60000 0110 ->->0000 0110-101000 1010 ->1111 0101 ->1111 0110-41000 0100<- 1000 0011<- 1111 1100
#include<stdio.h>
int main(){
char a
= 128;
char b
= -129;
char c
= 300;
unsigned char d
= 300;
printf("%d\n",d
);
return 0;
}
计算类型的最大值
#include<stdio.h>
int main(){
int a
= 0;
int b
= a
+1;
while(a
<b
){
a
++;
b
++;
}
printf("%d\n",a
);
return 0;
}