2018面试题
4.
下面是一个 C 语言程序从源代码到形成可执行文件的过程,请解释图
中的 ABCD 分别表示什么,在每个阶段分别完成了什么工作?
1、预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些代码输出到一个“.i”文件中等待进一步处理。
2、编译就是把C/C++代码(比如上面的".i"文件)“翻译”成汇编代码。
3、汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux系统上一般表现位ELF目标文件(OBJ文件)。
4、链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,最终生成可以在特定平台运行的可执行程序。
8
&: 二进制“与”(都为1时,结果是1,否则是0。)
|: 二进制“或”(有1时,结果是1,都是0时,结果为0。)
int f(unsigned int num)
{
for (unsigned int i = 0; num; i++) {
num &= (num - 1);
}
return i;
}
该程序计算一个数转化为二进制后1的个数
9
int main(int argc, char *argv[])
{
char n[] = { 1, 0, 0, 0 };
printf("%d\n", *(int *)n);
return 0;
}
1、操作系统在访问内存数据时是从低地址向高地址的顺序进行的,所以,对于大端模式就是从高位开始,而对于小端模式则从低位开始。
2、现在的计算机基本都是小端存储,所以最终将1存在了最低位,其他位都是0
3、n先于(int *)结合,进行强制类型转换,又因为n是一个地址,所以进行解引用读值
10
10. 分析以下代码段,解释输出的结果。
#define YEAR 2018
#define LEVELONE(x) "XiyouLinux "#x"\n" #define LEVELTWO(x) LEVELONE(x)
#define MULTIPLY(x,y) x*y
int main(int argc, char *argv[])
{
int x = MULTIPLY(1 + 2, 3);
printf("%d\n", x);
printf(LEVELONE(YEAR));
printf(LEVELTWO(YEAR));
}
1、宏定义里面有个##表示把字符串联在一起。
2、宏定义中的#表示将其变为字符串。
3、使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.
4、##是一个连接符号,用于把参数连在一起 例如:
> #define FOO(arg) my##arg 则
> FOO(abc) 相当于 myabc
14
编码题
不使用任何库函数,将字符串转化为整型数。
函数原型:int Convert(const char* num);
例子:char *str = “12345”; int res = Convert(str);
结果:res 应当为 12345。
#include<stdio.h>
#include<string.h>
#include<math.h>
int POW(int x,int n);
int Convert(const char *num);
int main(void)
{
char num[6]="12345";
printf("%d\n",Convert(num));
}
int POW(int x,int n)
{
int sum=1;
if(n==0)
return sum=1;
for(int i=1;i<=n;i++)
{
sum=sum*x;
}
return sum;
}
int Convert(const char *num)
{
int sum=0;
int t=strlen(num);
int k=t-1;
for(int i=0;i<t;i++)
{
sum=sum+(*(num+i)-48)*POW(10,k-i);
}
return sum;
}
15
- 编码题
输入一个整型数组,实现一个函数来调整该数组中数字的顺序,使
得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
#include<stdio.h>
#include<string.h>
#include<math.h>
int main(void)
{
int a[100];
int b[100];
int n;
printf("输入数组长度:");
scanf("%d",&n);
for(int i=0;i<n;i++) //输入数据
{
printf("第%d个数据:",i+1);
scanf("%d",&a[i]);
}
int k=0;
for(int i=0;i<n;i++) //挑选计数
{
if(a[i]%2==1)
{
b[k]=a[i];
k++;
}
}
for(int i=0;i<n;i++) //挑选偶数
{
if(a[i]%2==0)
{
b[k]=a[i];
k++;
}
}
for(int i=0;i<n;i++) //输出数据
{
printf("%d\t",b[i]);
}
}
2019面试题
1、
int main(int argc, char *argv[]) {
for (unsigned int i = 3; i >=0; i--)
putchar('=');
}
总结:
1、当i减到-1时,本应退出循环,但是由于i为unsigned int ,将最高位的符号位当做了数据位进行读取,所以会是一个很大的数,再次减到-1又会继续变成一个很大的数,进行无限循环
2
交换数值的三种方法
(1) */ int c = a; a = b ; b = c;
(2) */ a = a - b; b = b + a; a = b - a;
(3) */ a ^= b ; b ^= a ; a ^= b
^位异或运算 同为0异为1
4
1、printf 的嵌套会返回所有的打印字符,包括空格和不可见的换行字符
2、scanf返回成功读入的项目个数,当期望得到一个数字却输入非数字字符,那么scanf的返回值为0
5
& 表示按位与。1&1=1 1&0=0
| 表示按位或 1|1=1 1|0=1
^位异或运算 同为0异为1
11
11.斐波那契数列是这样的一串数列:1,1,2,3,5,8,13,…。在这串数列中,第一项、第二项
为 1,其他项为前两项之和,该数列的第 x 项可以表示为下面的函数。请根据描述,写出一个程
序,使之输入 x 后,能够输出斐波那契数列的第 x 项(其中 x<30)。当你完成之后,你可以尝试
使用递归解决这个问题。
?(?) = {
1, ? = 1 ?? ? = 2
?(? − 1) + ?(? − 2), ? ≥ 3
(? ∈ ?+)
#include<stdio.h>
int fb(int n);
int main(void)
{
int n;
scanf("%d",&n);
printf("%d\n",fb(n));
}
int fb(int n)
{
int t;
if(n==1 ||n == 2)
t=1;
else
t=fb(n-1)+fb(n-2);
return t;
}
13
13.请简单叙述两种字节序(大端、小端)的概念,你的机器是什么字节序?试着写一个 C 语言程
序来验证,如果你没有思路,你可以尝试着使用联合体或者指针。
数据从低地址向高地址存储
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int panduan (void);
int main(void)
{
if(panduan()==1)
printf("小端\n");
else
printf("大端\n");
}
int panduan(void)
{
int a=1;
return *(char *)&a;
}