西邮Linux兴趣小组2020纳新试题题解
感谢 Zhilu 重新录入题目原件。好人一生平安。
注:
- 本题仅作为面试有限参考
- 为节省版面,省去所有
#include
指令- 题目难度与序号无关
- 若无特殊声明,均假设在
Linux x86_64 GCC
编译器环境下
1. 请试着解释其输出。
int main(int argc , char *argv[]) {
unsigned char a = 255;
char ch = 128;
a -= ch;
printf("a = %d ch = %d\n", a, ch);
}
题解:
结果:
a = 127 ch = -128
char最大值=127
给char类型赋值128 会溢出变成-128
运行表达式时依旧会带入赋给的值进行运算。
2. 下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[]) {
char *str = "Xi You Linux Group 20";
printf("%d\n", printf(str));
return 0;
}
同 22-1
3. 这段代码的输出结果是什么?为什么会出现这样的结果?
int i = 2;
void func() {
if(i != 0) {
static int m = 0;
int n = 0;
n++;
m++;
printf("m = %d, n = %d\n", m, n);
i--;
func();
} else {
return;
}
}
int main(int argc, char *argv[]) {
func();
return 0;
}
题解:
递归两次
m是静态变量,一次函数运行完内存不会释放,所以m=2
n同理,加了一次后,内存释放
m = 2, n = 1
4. 下面程序会出现什么结果?为什么会出现这样的结果?
int main(int argc, char * argv[]) {
char ch = 'A';
int i = 65;
unsigned int f = 33554433;
*(int *)&f >>= 24;
*(int *)&f = *(int *)&f + '?';
printf("ch = %c i = %c f = %c\n", ch, i, *(int *)&f);
return 0;
}
题解:
ch = A i = A f = A
字符存放的其实为ASCII值,65对应’A’,同样f进行运算时使用ASCII码值,输出代表的字符。
5. 下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[]) {
int a[2][2];
printf("&a = %p\t&a[0] = %p\t&a[0][0] = %p\n", &a, &a[0], &a[0][0]);
printf("&a+1 = %p\t&a[0]+1 = %p\t&a[0][0]+1= %p\n", &a+1, &a[0]+1, &a[0][0]+1);
return 0;
}
题解:
&a = 0x7ffdd8cf8fb0 &a[0] = 0x7ffdd8cf8fb0 &a[0][0] = 0x7ffdd8cf8fb0
&a+1 = 0x7ffdd8cf8fc0 &a[0]+1 = 0x7ffdd8cf8fb8 &a[0][0]+1= 0x7ffdd8cf8fb4
&a进行运算对象为整个数组,&a[0]进行运算对象为第0行数组,&a[0][0]进行运算对象为第0行第0个元素。
详细见22年指针和数组的举例
6. 下列程序的功能是什么?有什么问题,你能找出问题并解决它吗?
int* get_array() {
int array[1121];
for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
array[i] = i;
}
return array;//返回的是局部变量的地址
}
int main(int argc, char *argv[]) {
int *p = get_array();
}
题解:
问题 :for循环结束后array[1121]释放内存, 所以返回地址然而找不到对应的变量
将array定义为全局变量
7. 下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[]) {
char str[] = "XiyouLinuxGroup";
char *p = str;
char x[] = "XiyouLinuxGroup\t\106F\bamily";
printf("%zu %zu %zu %zu\n", sizeof(str), sizeof(p), sizeof(x), strlen(x));
return 0;
}
题解:
答案:16 8 25 24
sizeof(str)结果计算末尾的’\0’
sizeof§结果得到指针变量的大小
sizeof(x)结果计算末尾的’\0’
[\t \106 \b为转义字符,只占一个字符大小]
strlen(x)结果不计算末尾的’\0’
8. 如下程序,根据打印结果,你有什么思考?
int add(int *x, int y) {
return *x = (*x^y) + ((*x&y)<<1);
}
int a;
int main(int argc, char *argv[]) {
int b = 2020;
if(add(&b, 1) || add(&a, 1)) {
printf("XiyouLinuxGroup%d\n", b);
printf("Waiting for y%du!\n", a);
}
if(add(&b, 1) && a++) {
printf("XiyouLinuxGroup%d\n", b);
printf("Waiting for y%du!\n", a);
}
return 0;
}
答案:
XiyouLinuxGroup2021
Waiting for y0u!
同22-5
9. 在下段程序中,我们可以通过第一步打印出a
的地址,假如在你的机器上面打印结果是0x7ffd737c6db4
;我们在第二步用scanf
函数将这个地址值输入变量c
中;第三步,随机输入一个数字,请问最终输出了什么结果,你知道其中的原理吗?
void func() {
int a = 2020;
unsigned long c;
printf("%p\n", &a);//打印a的地址
printf("我们想要修改的地址:");
scanf("%lx", &c);//将地址的16进制值赋值给无符号长整形c
printf("请随便输入一个数字:");
scanf("%d", (int *)c);//将c进行强制类型转换变成指针并输入数
printf("a = %d\n", a);//a=输入的数字
}
改变地址存的数值
10. 请问一个C语言程序从源代码到可执行文件中间会进行哪些过程,你能简单描述一下每个环节都做了什么事情吗?
1.预处理(主要处理代码中以字符#开头的命令)
2.编译
3.汇编(把汇编语句转换为机器指令)
4.链接(链接器将所有二进制的目标文件和系统组件组合成一个可执行文件(.exe))
11. 请解释一下这行代码做了什么?
puts((char*)(int const[]){
0X6F796958,0X6E694C75,0X72477875,
0X3270756F,0X313230,0X00000A
});
同22-12
12. 请随机输入一串字符串,你能解释一下输出结果吗?
int main(int argc, char *argv[]) {
char str[1121];
int key;
char t;
fgets(str, 1121, stdin);//从 stream 流中读取 size 个字符存储到字符指针变量 s 所指向的内存空间。它的返回值是一个指针,指向字符串中第一个字符的地址。
for(int i = 0; i < strlen(str) - 1; i++) {
key = i;
for(int j = i + 1; j < strlen(str); j++) {
if(str[key] > str[j]) {
key = j;
}
}
t = str[key];
str[key] = str[i];
str[i] = t;//类似冒泡,对字符的排序
}
puts(str);//打印字符串
return 0;
}
排序字符串
13. 用循环和递归求Fibonacci
数列,你觉得这两种方式那种更好?说说你的看法。如果让你求Fibonacci
数列的第100项,你觉得还可以用常规的方法求解吗?请试着求出前100项的值(tip大数运算)。
//递归
#include <stdio.h>
int Fibonacci(int n)
{
if (n <= 2)
return 1;
else
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
int main()
{
int n;
scanf("%d", &n);
int x=Fibonacci(n);
printf("%d", x);
return 0;
}
//循环
#include <stdio.h>
long long int a = 1, b = 1;
long long int c = 0;
int n, i;
int main()
{
scanf("%d", &n);
for (i = 3; i <= n; i++)
{
c = a + b;
a = b;
b = c;
}
printf("%lld", c);
return 0;
}
递归 方便快捷,but数字大时运行速度太慢
循环较为快捷
14. Linux 实操题
请通过命令创建一个目录,在该目录中创建几个后缀为
.Linux
的文件,然后通过命令查询这几个文件的基本属性信息(如文件大小,文件创建时间等),之后使用命令查看该目录下文件名含有“.Linux
”的文件的数量(不包括子目录下的文件),把得到的数字写入到一个文件中,最后删除此目录。
mkdir awa
touch awa1/awa2.Linux
stat awa1.Linux
cd:awa
rm -r awa