题目来自牛客网,刷题链接:牛客网专项练习_校招题库练习题_行测题库考点考题 (nowcoder.com)https://www.nowcoder.com/exam/intelligent
1、在32位操作系统中,char*a="12",sizeof(a)是多少?
答案:4
解析:a是一个指针,在32位操作系统中,地址是32位,故占四个字节。
2、假如整型指针p已经指向某个整型变量x,则(*p)++和下面哪一个等价?
A、p++
B、x++
C、*(p++)
D、&x++
答案:B
解析:在(*p)++中括号的优先级最高,指针p指向x,那么*p等价于x。所以(*p)++等价于x++
3、以下能正确定义一维数组的选项是
A、int a[5]={0,1,2,3,4,5};
B、char a[]={0,1,2,3,4,5};
C、char a={'A','B','C'};
D、int a[5]="0123";
答案:B
解析:选项A申请了5个整型元素的空间大小,存储了六个数,错误。选项B是将后面的整型数据根据ASCII码表转换成字符型数据存储到字符数组中的,正确。选项C定义的不是一个数组,错误。选项D定义的是一个一维整型数组,要存储的却是一个字符串,错误。
4、以下叙述中正确的是
A、由printf输出的数据都隐含左对齐
B、scanf和printf是C语言提供的输入和输出语句
C、赋值语句是一种执行语句,必须放在函数的可执行部分或全局区域
D、由printf输出的数据的实际精度是由格式控制中的域宽和小数的域宽来完全决定的
答案:C
解析:由printf输出的数据隐含右对齐,选项A错误。
scanf和printf是C语言提供的输入和输出函数,不是语句,选项B错误。函数分为函数头部和函数体,赋值语句要在函数体中,也就是可执行部分。或者在函数外部的全局区域进行赋值,选项C正确。由printf输出的数据的实际精度是由系统决定的,取决于在内存中的存储方式和计算过程中的处理。而格式控制中的域宽和小数的域宽不影响数据实际的精度,影响的是数据的显示形式。选项D错误。
5、以下程序段的输出结果为( )
1
2
3
for
(
int
i = 4; i > 1; i--)
for
(
int
j = 1; j < i; j++)
putchar
(
'#'
);
A、无
B、######
C、#
D、###
答案:B
解析:这里for都没有加{},作用的只是其下面的一条语句。但是经过观察,仍然是一个循环的嵌套,特点是外层执行一次,内层执行一轮。
第一次,i=4,内层循环输出三个#
第二次,i=3,内层循环输出两个#
第三次,i=2,内层循环输出一个#
循环结束。
共输出六个#,选择B。
6、设p是指针变量,语句P = NULL;等价于?
A、p = '0 ';
B、P = ‘’;
C、P = "" ;
D、p = 0;
答案:D
解析:p='0'这种表达本就是不合理的,p是一个指针变量,'0'是一个字符常量,不是一个地址。所以选项A错误。p=‘’,它将一个内容为空的字符赋值给p,两边类型不一致,也是不合理的,选项B错误。p=“”,它将一个空字符串的首地址赋值给p,但这个地址并不等价于NULL。选项C错误。p = 0,c语言中,NULL与数字0是等价的,其ASCII码都为零。选项D正确。
7、C 语言代码中,若整型变量 i 的值为偶数,那么值为 true 的逻辑表达式是 ()
A、i%2=0
B、i%2!=1
C、i/2==0
D、i%2 equals 0
答案:B
解析:结合题干,需要选出一个能判断i为偶数的逻辑表达式,排除选项A和选项B,判断是否为偶数,应该进行的是取余操作,综合看下来选择选项B。
8、下面程序的执行结果为()
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int
func(
int
n) {
if
(n < 2)
return
n;
return
func(n - 1) + func(n - 2);
}
int
main () {
printf
(
"%d\n"
,func(7));
return
0;
}
A、11
B、13
C、17
D、21
答案:B
解析:这道题一步一步推也可以选出答案,整体是一个递归的思想。并且可以发现func(0)到func(7)符合一个斐波那契数列的规律。
9、有以下程序
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <string.h>
void
fun(
char
*s) {
char
a[10];
strcpy
(a,
"STRING"
);
s = a;
}
main() {
char
*p =
"PROGRAM"
;
fun(p);
printf
(
"%s\n"
, p);
}
程序运行后的输出结果是(此处□代表空格)?
A、STRING
B、STRING□□□□
C、STRING□□□
D、PROGRAM
答案:D
解析:在函数的传参过程中,系统会专门给形参开辟空间,所以形参和实参存储在不同的地方,实参可以改变形参,但形参不能改变实参。以本题为例,传递的只是指针p的副本,并不是指针p的本身,所以在调用函数中改变形参的指向并不会影响指针p本身。在刚传递过去是,p和s都指向"PROGRAM",在执行了s=a后,只是将s的指向改变,p的指向从始至终都没有变,也就是形参不能改变实参的意思。
10、char *p="girl";的含义是定义字符型指针变量 p,p 的值是字符串"girl"。请问这句话的说法是正确的吗?
答案:错误
解析:首先要记住指针即地址,地址即指针。在本例中指针p中存放的是字符串"girl"的首地址。
11、 程序最后输出什么?( )
1
2
3
4
5
6
7
8
9
10
#define Mul(x,y) ++x*++y
void
main()
{
int
a = 1;
int
b = 2;
int
c = 3;
printf
(“%d”,Mul(a+b,b+c));
}
A、14
B、24
C、48
D、18
答案:A
解析:这个题主要考察了两点,一个是宏定义,一个是优先级的问题。宏定义是整体的替换,不会自动加括号,按规则直接写上去即可。经过宏定义转换后Mul(a+b,b+c)成为++a+b*++b+c,根据出现运算符的优先级(++ > * > +),首先a和b进行自增操作,代入值后式子变为2+3*3+3,然后先乘法后加法得出结果为14。
12、若有以下定义,说法错误的是()
1
int
a = 100, *p = &a;
A、声明变量p,其中*表示p是一个指针变量
B、变量p经初始化,获得变量a的地址
C、变量p只可以指向一个整形数据
D、变量p的值为100
答案:D
解析:声明指针时,*是一个指针运算符,代表声明的是一个指针变量。除声明时外,*是解引用,是取得指针指向目标的意思,选项A正确。p是一个指针,指针的值应该是一个地址,*p的值才是100,选项D错误。
13、若有宏定义:
1
#define S(a,b) t=a;a=b;b=t
由于变量 t 没定义,所以此宏定义在编译时是错误的。请问这句话的说法是正确的吗?
A、正确
B、错误
答案:错误
解析:C语言中,宏定义是通过预处理器进行处理的,并不是编译阶段或运行时进行处理的。预处理是在编译之前的工作,预处理中不做语法检查,语法检查是编译阶段的工作。如果仅是进行宏定义的话,不会出现错误,如果在代码中使用S(a,b)才会发生错误。
14、对于指针运算,下面说法错误的是()
A、可以用一个空指针赋值给某个指针变量
B、两个指针可以进行加法运算
C、如果一个指针指向数组元素,指针可以加上一个整数
D、如果一个指针指向数组元素,该指针可以执行自增自减运算
答案:B
解析:空指针指向NULL,也是一个地址,可以赋值给其他指针变量,选项A正确。指针只有减法运算,没有加法、乘法等运算,没有实际的意义,编译器也不会通过,选项B错误。C选项中指针加上一个整数,表示指针前后移动相应的位置,选项C正确。自增自减运算同样是指针进行移动,D选项正确。
15、则a[q - p] = ?
1
2
3
4
5
6
7
int
a[3];
a[0] = 0;
a[1] = 1;
a[2] = 2;
int
*p, *q;
p = a;
q = &a[2];
A、0
B、1
C、2
D、未知
答案:2
解析:q-p求的实际是两个地址间有几个int型变量的空间。所以本题中q-p等于2,结果为a[2] = 2
16、以下程序运行后的输出是()
1
2
3
4
5
6
7
#include <stdio.h>
int
main(
void
){
int
x =
10
, y =
20
, t =
0
;
if
(x == y) t = x; x = y; y = t;
printf(
"%d, %d\n"
, x, y);
return
0
;
}
A、10, 20
B、20, 0
C、10, 0
D、20, 10
答案:B
解析:代码中的if不带{},作用域仅为下面离他最近的一条语句,所以t=x不会执行,之后的两条语句会执行,所以结果为20,0
17、 下⾯函数的功能是()
1
2
3
4
5
int
fun (
char
*s) {
char
*p = s;
while
(*p++);
return
p-s-1;
}
A、计算字符串的位(bit)数
B、复制⼀个字符串
C、求字符串的长度
D、求字符串存放的位置
答案:C
解析:首先,s指向的地址应该是字符串的首地址,将s指向的地址赋值给p,然后p移动到字符串的'\0'位置结束循环,结束循环后,p还会向后移动一个位置指向字符数组的第二个'\0'。最后因为是字符类型的指针,二者相减为字符串的总长度,再减去1是不包含'\0'的有效长度。
18、存在int类型变量x,y,z,其对应值为x=0x59,y=0x39,z=0x6E,则x*y+z的值为()
A、1001001110011
B、1010000111111
C、1001001110111
D、1011001111111
答案:B
解析:这个题目直接模仿十进制数的算数运算,要注意的是,此处满16进一,最后再换算成二进制即可。
19、若x为int型变量,则执行以下语句后x的值为-24.
1
2
x = 6;
x += x -= x * x;
说法是否正确?
A、正确
B、错误
答案:B
解析:首先赋值运算符的优先级要低于*,原式化为x += x -= 36,接着依据赋值运算符的结合方向为从右向左,所以先进行x-=36,x此时等于-30,再进行x+=-30,最终结果为-60。
20、
1
2
3
4
5
int
x =5;
const
int
*
const
p = &x;
const
int
&q=x;
int
const
*next=&x;
const
int
*j=&x;
则有语法错误的是()
A、* p =1;
B、q++;
C、next++;
D、(*j)++;
答案:ABD
解析:解决这个问题,主要是搞清楚const修饰的是哪一个。在第二句const int * const p = &x中,第一个const修饰的是指针指向的目标,第二个const修饰的是指针本身,所以既不能改变指针p的指向,也不能通过指针p去修改x的值。所以选项A错误。第三句const int &q = x中,声明了一个对整型常量x的引用q,声明后不可通过q修改x的值,也不可修改q,选项B错误。第四句int const *next=&x中,指针的目标被常量化,指针指向还是可以修改的,选项C正确。第五句const int *j = &x中同样是常量化指针目标,所以不可以通过指针j改变x的值,选项D错误。
21、 以下函数按每行5个输出数组中的数据
1
2
3
4
5
6
void
f(
int
x[],
int
n){
for
(
int
i = 0;i < n;i++){
__________________________
printf
(
"%d"
, x[i]);
}
}
下划线处应填入的语句是( )
A、if(i / 5 == 0)printf(“\n”);
B、if(i / 5 == 0)continue;
C、if(i % 5 == 0)printf(“\n”);
D、if(i % 5 == 0)continue;
答案:C
解析:所填语句下面是打印语句,那么所填语句的作用应该是进行换行,题目中又要求每行五个输出,所以选择选项C。
22、 C 语言中的标识符以字母或下划线开头,可跟任何字符。请问这句话的说法是正确的吗?
A、正确
B、错误
答案:错误
解析:在C语言中,定义一个标识符要遵守以下规则:
1、只能由字母、数字、下划线构成。
2、不能以数字开头。
3、不能与关键字重名
题目中说可以跟任何字符,很容易举出反例,比如后面接了标点符号,所以题目的话错误。
23、 设 a,b,c 为整型变量,执行下面语句
1
2
3
4
5
a = 2;
b = 9;
a++;
c = --b;
a += b - c;
后 a 的值为( )
A、7
B、4
C、3
D、2
答案:C
解析:本题主要考察运算符的优先级。
第三行,a自增,此时a=3
第四行,由于b的自减是前置的,所以b先自减,再赋值给c,此时b=8,c=8
第五行,根据运算符的优先级,-的优先级大于+=,所以式子可以化为a+=0,a的值最后为3
24、
1
2
3
4
5
6
7
#include <stdio.h>
int
main() {
char
*a[] = {
"work"
,
"at"
,
"alibaba"
};
char
**pa = a;
pa++;
printf
(
"%s"
, *pa);
}
下列程序的执行结果是()
A、at
B、atalibaba
C、ork
D、orkatalibaba
E、编译错误
F、运行溢出
答案:A
解析:题目中首先定义了一个指针数组,这个指针数组中,每一个元素都指向了一个字符串的首地址。接着定义了一个二级指针,它指向了指针数组的首地址。现在执行pa++后,二级指针pa将指向指针数组的的下一个元素,也就是指向字符串"at"的指针。对pa进行解引用,得到的是a[1],a[1]的内容是字符串"at"的首地址。所以最后以%s对其进行输出得到的结果是at。
25、
以下函数调用语句中实参的个数是( )
1
exce((v1, v2), (v3, v4, v5), v6);
A、3
B、4
C、5
D、6
答案:A
解析:这条语句中,考察了逗号表达式,实际的上的实参为v2、v5、v6,共三个参数。
26、判断字符串s1是否小于字符串s2,应当使用()
A、if(s1>s2)
B、if(strcmp(s1,s2))
C、if(strcmp(s2,s1)>0)
D、if(strcmp(s2,s1)<0)
答案:C
解析:题目要判断的是字符串s1是否小于字符串s2,那么结果为小于时,if中的表达式应该为真,符合条件的是选项C。字符串s1小于字符串s2时,strcmp的结果大于零,表达式为真。
关于strcmp()函数的用法。strcmp(字符串1,字符串2),从左往右将字符串1的每个字符都与字符串2中对应位置的字符进行比较,如果都一样,返回0。如果出现不一样的字符则返回两个字符的差(字符串1中字符减字符串2中字符)。
27、 下述程序的输出是______。
1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int
main()
{
static
char
*s[] = {
"black"
,
"white"
,
"pink"
,
"violet"
};
char
**ptr[] = {s+
3
, s+
2
, s+
1
, s}, ***p;
p = ptr;
++p;
printf(
"%s"
, **p+
1
);
return
0
;
}
A、ink
B、pink
C、white
D、hite
答案:A
解析:首先定义了一个一级指针数组,其中的四个一级指针分别指向四个字符串的首地址。
然后定义了一个二级指针数组,其中的四个二级指针分别指向对应的一级指针数组的一级指针。接下来定义了一个三级指针,指向二级指针数组的首地址。执行++p,那么p移动一个位置,指向二级指针数组第二个元素的位置。执行**p+1,由于*的优先级高于+,则先执行*,*p得到指针ptr[2],**p得到指针s[2]。此时指针s[2]指向字符串"pink"的'p',再加一,指向'i'。最后以%s输出得到ink。
28、以下不是无限循环的语句为()
A、for(y=0,x=1;x>++y;x=i++) i=x;
B、for(;;++x=i);
C、while(1){x++;}
D、for(i=10;;i--) sum+=i;
答案:A
解析:选项A中x的值为1,第一次进行判断时,++y的值也为1,不会进入循环体。选项B和选项D中都对循环的表达式2进行了省略,所以是死循环。 选项C,while(1)是经典定义死循环的形式,表达式恒为真。
29、以下对一维数组a的定义正确的是()
A、int n = 5, a[n];
B、int a(5);
C、const int N = 5; int a[N];
D、int n; cin>>n; int a[n];
答案:C
解析:在C99标准之后只要[ ]中的数在定义数组时是确定的即可,在C99标准前是不支持变长数组的,所以选项A和选项D排除。选项B定义数组的形式书写错误。综合来看,只有C选项符合条件,N为一个常量。
30、 以下程序输出结果是:
1
2
3
4
5
6
7
8
int
main ()
{
int
m=
5
;
if
(m++>
5
)
printf (
"%d\n"
,m);
else
printf (
"%d\n"
,m--);
}
A、7
B、6
C、5
D、4
答案:B
解析:m被初始化为5,判断m++>5是否成立,因为这是一个后++,所以会先进行比较再进行++,所以表达式为假。表达式为假会进入到else中,此时m完成了++操作,值为6。下面看printf中,输出的是m--,同样是因为这是一个后--,会先输出值,再进行--操作。综上,输出的值为6,选择选项B。
31、 对if语句中表达式的类型,下面正确的描述是()
A、必须是关系表达式
B、必须是关系表达式或逻辑表达式
C、必须是关系表达式或算术表达式
D、可以是任意表达式
答案:D
解析:if语句中的表达式可以是任意表达式,只要符合C语法,包括关系表达式、逻辑表达式、算数表达式等。表达式非零即为真,否则就为假。
32、 以下叙述中正确的是()
A、字符串常量"str1"的类型是:字符串数据类型
B、有定义语句: char str1[] = "str1"; ,数组str1将包含4个元素
C、下面的语句用赋初值方式来定义字符串,其中,'\0'是必须的 char str1[] = {'s', 't', 'r', '1', '\0'};
D、字符数组的每个元素可存放一个字符,并且最后一个元素必须是'\0'字符
答案:D
解析:C语言中没有字符串数据类型,故选项A错误。选项B中定义的是一个字符数组用来存储字符串,字符串是以'\0'结尾的,所以应该包含了5个元素,故选项B错误。在选项C这种定义方式中,如果不加入'\0',就只是一个普通的字符数组,而不是字符串,所以选项C正确。字符数组常常用来存储字符串,而字符串以'\0'结尾,但是二者并不等价,当字符数组只是用来存储字符时,不需要最后一个元素必须是'\0'。
33、 假设所有变量均为整型,则表达式(a = 2, b = 3, b++, a + b)的值是5。请问这句话的说法是正确的吗?
A、正确
B、错误
答案:B
解析:本题考查逗号表达式。所有式子会从左往右依次执行,但是只返回最后一个表达式的值,所以表达式的值应该为6。但是要注意的是,如果最后一个表达式是后++,那么就会先把值返回,再自增。
34、 下面程序的输出是:
1
2
3
4
5
6
#define f(x) x*x
#include<stdio.h>
main (){
int
a = 6, b = 2, c;
c = f(a) / f(b);
printf
(
"%d"
, c); }
A、3
B、18
C、36
D、9
答案:C
解析:本题考查的是宏定义。宏定义的核心是进行替换,那么替换后c = 6*6/4*4,按照规则应该从左往右运算,结果是36。
35、下面四个选项中,均是不合法的浮点数的选项是()
A、160. 0.12 e3
B、123 2e4.2 .e5
C、-.18 123e4 0.0
D、-e3 .234 1e3
答案:B
解析:在C语言中浮点数有两种形式,分别为十进制小数形式和指数形式。指数形式的一般形式为 a E n,a和n都不可以省略,其中a是一个十进制数,n是一个十进制整数。经过判断只有选项B中三个数均不是合法的浮点数。
36、阅读程序,下面程序的输出结果是()
假设可执行文件的文件名为prog.exe,运行时键入的命令行为prog -386 net↙
1
2
3
4
5
6
7
#include <
stdio.h
>
int main (int argc, char *argv[ ]) {
int i;
for(i=0;i< argc; i++)
printf(“%s",argv[i]);
return 0;
}
A、-386 net
B、prog.exe -386 net
C、prog.exe -386
D、prog -386 net
答案:D
解析:这道题考察的是main函数参数的含义。main函数的两个参数argc和argv[ ]分别存储着输入命令行参数的个数和指向命令行参数字符串的指针,所以整个代码的含义就是将命令行中输入的命令行参数进行输出。
37、 有以下程序
1
2
3
4
5
#include <stdio.h>
main(){
int
a = 2, c = 5;
printf
(
"a=%%d,b=%%d\n"
, a, c);
}
则程序的输出结果是()
A、a=2,b=5
B、a=%2,b=%5
C、a=%d,b=%d
D、a=%%d,b=%%d
答案:C
解析:%%输出为%,后面的只剩下了d而不是%d会原样打印,所以最后输出a=%d,b=%d。
38、 C语言中,函数值类型的定义可以缺省,此时函数值的隐含类型是( )
A、void
B、int
C、float
D、double
答案:B
解析:在C语言中,如果函数未指定返回值类型,则默认为int类型 。在C++中,如果一个函数没有返回值,返回值类型必须指定为void。
39、 a=3*5 , a*4; 最终a为60.是否正确?
A、正确
B、错误
答案:B
解析:本题考查的是逗号运算符,首先会计算3*5赋值给a,则a=15,然后计算a*4结果为60,但是没有赋值操作,所以a最后的结果还是15。
40、 以下程序的输出结果是
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int
a, b;
void
fun() {
a = 100;
b = 200;
}
int
main() {
int
a = 5, b = 7;
fun();
printf
(
"%d %d\n"
, a, b);
return
0;
}
A、100 200
B、5 7
C、200 100
D、7 5
答案:B
解析:在main函数中定义了局部变量a和b,会把全局变量a和b给覆盖掉。在main函数中虽然调用了fun(),但是并没有进行传参,所以在调用函数中修改的是全局变量a和b的值,对于main函数中局部变量a和b的值没有影响。所以结果为5 7。
41、下列程序的输出结果是
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using
namespace
std;
void
f() {
static
int
i = 15;
i++;
cout <<
"i="
<< i << endl;
}
int
main(
void
){
for
(
int
k = 0;k < 2;k++)
f();
}
A、i=16 i=15
B、i=15 i=17
C、i=16 i=17
D、i=15 i=16
E、i=15 i=18
答案:C
解析:被static修饰的变量只会初始化一次,所以第二次调用函数f()时,i不会被初始化,值为16,自增后为17。所以答案为C选项。
42、以下叙述中正确的是()
A、预处理命令行必须位于源文件的开头
B、在源文件的一行上可以有多条预处理命令
C、宏名必须用大写字母表示
D、宏替换不占用程序的运行时间
答案:D
解析:预处理命令通常位于源文件的开头,但这并不是必须的,只要在被引用之前即可,所以选项A错误。根据标准C的规定,在源文件一行上只能有一条预处理命令,所以选项B错误。宏名通常用大写字母表示,但这也不是必须的,只要符合标识符的命名规则即可,所以选项C错误。宏替换是在编译前的预处理阶段进行的,不会占用程序的运行时间,所以选项D正确。
43、 x是一个行列数均为1000二维数组,下面代码效率执行最高的是()
A、for(int j=0;j<1000;j++) for(int i=0;i<1000;i++) x[i][j]+=x[j][i];
B、for(int i=0;i<1000;i++) for(int j=0;j<1000;j++) x[i][j]+=x[j][i];
C、for(int i=0;i<1000;i++) for(int j=0;j<1000;j++) x[j][i]+=x[j][i];
D、for(int i=0;i<1000;i++) for(int j=0;j<1000;j++) x[i][j]+=x[i][j];
答案:D
解析:这题考查了二维数组在内存空间中的存储方式。二维数组在内存中是按行进行存储的,在读取数据时,CPU会有一个预取操作,提前找到后面的数据。所以当一行一行进行遍历时,代码效率最高。
44、在32位机器中,如下代码:
1
2
3
4
5
6
7
8
9
void
example(
char
acWelcome[]){
printf(
"%d"
, sizeof(acWelcome));
return
;
}
void
main(){
char
acWelcome[] =
"Welcome to Huawei Test"
;
example(acWelcome);
return
;
}
的输出是?
A、0
B、4
C、23
D、24
答案:B
解析:当数组作为参数传递时会退化为指针,此时的形参并不能代表数组,只是一个指向数组首地址的指针,所以我们在定义和数组相关的函数时,常常也会传递数组的大小过去。所以sizeof运算符在这里就是在求一个指针的大小,因为是在32位机器中,故大小为4,选择选项B。
45、执行以下代码段(程序已包含所有必需的头文件)会输出什么结果。()
1
2
3
4
char
a[3];
char
b[] =
"good"
;
a = b;
printf
(
"%s"
, a);
A、go
B、goo
C、good
D、编译出错
答案:D
解析:此题中的a是一个地址常量,不能对其进行赋值操作。
46、 下列叙述中,错误的是:
A、计算机不能直接执行C语言编写的源程序。
B、C程序经编译后,生成的扩展名为.obj的文件是一个二进制文件。
C、扩展名为.obj的文件,经链接程序生成扩展名为.exe的文件是一个二进制文件。
D、扩展名为.obj和.exe的二进制文件都可以直接运行。
答案:D
解析:要明确整个编译的过程:
1、预处理:展开头文件和宏定义 .c文件变为.i文件
2、编译:检查语法错误 .i文件变为.s文件
3、汇编:生成计算机能够识别的二进制文件 .s文件变为.o文件
4、链接:生成最终的可执行文件 .o文件变为可执行文件