西邮Linux兴趣小组2021纳新面试题题解
注:
- 本题目仅作
西邮Linux兴趣小组
2021纳新面试题的有限参考。- 为节省版面本试题的程序源码中省略了
#include
指令。- 本试题中的程序源码仅用于考察C语言基础,不应当作为C语言代码风格的范例。
- 题目难度与序号无关。
- 所有题目均假设编译并运行
x86_64 GNU/Linux
环境。Copyright © 2021 西邮Linux兴趣小组, All Rights Reserved.
本试题使用采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
文章目录
- 1. 大小和长度竟然不是一个意思
- 2. 箱子的大小和装入物品的顺序有关
- 3. 哦,又是函数
- 4.就不能换个变量名吗?
- 5. 套娃真好玩!
- 6. 算不对的算术
- 7. 指针和数组的恩怨情仇
- 8. 移形换位之术
- 9. 听说翻转字母大小写不影响英文的阅读?
- 10. 交换礼物的方式
- 11. 据说有个东西叫参数
- 12. 人去楼空
- 13. 奇怪的输出
- 14. 请谈谈对从「C语言文件到可执行文件」的过程的理解
- 15. (选做) 堆和栈
- 16. (选做) 多文件
- 17. (选做) `GNU/Linux`与文件
1. 大小和长度竟然不是一个意思
sizeof()
和strlen()
有什么异同之处?他们对于不同参数的结果有什么不同?请试举例子说明。
int main(void) {char s[] = "I love Linux\0\0\0";int a = sizeof(s);int b = strlen(s);printf("%d %d\n", a, b);
}
a
为sizeof(s)
,即字符数组['I', ' ', 'l', 'o', 'v', 'e', ' ', 'L', 'i', 'n', 'u', 'x', '\0', '\0', '\0']
的大小;b
为strlen(s)
,即字符数组"I love Linux"
的长度。
另外,如果声明char s[20] = "I love Linux\0\0\0";
,则a = sizeof(s);
的值变为20
。
2. 箱子的大小和装入物品的顺序有关
test1
和test2
都含有:1个short
、1个int
、1个double
,那么sizeof(t1)
和sizeof(t2)
是否相等呢?这是为什么呢?
struct test1 {int a;short b;double c;
};
struct test2 {short b;int a;double c;
};
int main(void) {struct test1 t1;struct test2 t2;printf("sizeof(t1): %d\n", sizeof(t1));printf("sizeof(t2): %d\n", sizeof(t2));
}
解读:
struct test1 {int a; // 0 ~ 3short b; // 4 ~ 5double c; // 8 ~ 15
} t1; // 0 ~ 15 -> 16
struct test2 {short b; // 0 ~ 1int a; // 4 ~ 7double c; // 8 ~ 15
} t2; // 0 ~ 15 -> 16
3. 哦,又是函数
想必在高数老师的教导下大家十分熟悉函数这个概念。那么你了解计算机程序设计中的函数吗?请编写一个
func
函数,用来输出二维数组arr
中每个元素的值。
/*在这里补全func函数的定义*/
int main(void) {int arr[10][13];for (int i = 0; i < 10; i++) {for (int j = 0; j < 13; j++) {arr[i][j] = rand();}}func(arr);
}
补全后:
#include <stdio.h>
#include <stdlib.h>
void func(int a[10][13]) {for (int i = 0; i < 10; i++) {for (int j = 0; j < 13; j++)printf("%d ", a[i][j]);printf("\n");}
}
int main(void)
{int arr[10][13];for (int i = 0; i < 10; i++) {for (int j = 0; j < 13; j++) {arr[i][j] = rand();}}func(arr);
}
4.就不能换个变量名吗?
- 请结合下面的程序,简要谈谈
传值
和传址
的区别。- 简要谈谈你对C语言中变量的生命周期的认识。
int ver = 123;
void func1(int ver) {ver++;printf("ver = %d\n", ver);
}
void func2(int *pr) {*pr = 1234;printf("*pr = %d\n", *pr);pr = 5678;printf("ver = %d\n", ver);
}
int main() {int a = 0;int ver = 1025;for (int a = 3; a < 4; a++) {static int a = 5;printf("a = %d\n", a);a = ver;func1(ver);int ver = 7;printf("ver = %d\n", ver);func2(&ver);}printf("a = %d\tver = %d\n", a, ver);
}
传值
后,修改形参的值,实参的值不会改变。传址
后,修改形参的值,实参的值会改变。
解读:
#include <stdio.h>
int ver = 123;
void func1(int ver) {\// ver@func1ver++;// ver@func1 = 1026 printf("ver = %d\n", ver);// ver@func1 is discarded
}
void func2(int *pr) {*pr = 1234;// *pr@func2(as ver@loop in main) = 1234 printf("*pr = %d\n", *pr);pr = 5678;printf("ver = %d\n", ver);// ver@global = 123// *pr@func2 is discarded, but ver@loop isn't
}
int main() {int a = 0;int ver = 1025;for (int a = 3; a < 4; a++) {static int a = 5;// a@loop = 5printf("a = %d\n", a);a = ver;// a@loop = 1025func1(ver);int ver = 7;// ver@loop = 7printf("ver = %d\n", ver);func2(&ver);// jump out of loop, and a@loop and ver@loop are discarded}// a@main = 0, ver@main = 1025printf("a = %d\tver = %d\n", a, ver);
}
5. 套娃真好玩!
请说明下面的程序是如何完成求和的?
unsigned sum(unsigned n) { return n ? sum(n - 1) + n : 0; }
int main(void) { printf("%u\n", sum(100)); }
通过递归完成求和,每次递归返回的为其先前的数之和。相当于栈(Stack)
,只有其前的函数的表达式返回值(出栈),新的栈顶函数表达式才能返回值。
特别地,当栈顶元素为sum(0)
时,会返回0
以实现从0
到n
的求和。
6. 算不对的算术
void func(void) {short a = -2;unsigned int b = 1;b += a;int c = -1;unsigned short d = c * 256;c <<= 4;int e = 2;e = ~e | 6;d = (d & 0xff) + 0x2022;printf("a=0x%hx\tb=0x%x\td=0x%hx\te=0x%x\n", a, b, d, e);printf("c=Ox%hhx\t\n", (signed char)c);
}
#include <stdio.h>
void func(void) {short a = -2;// a = 1111 1111 1111 1110unsigned int b = 1;b += a;// b = 1111 1111 1111 1111 1111 1111 1111 1111int c = -1;// c = 1111 1111 1111 1111 1111 1111 1111 1111unsigned short d = c * 256;// d = 1111 1111 0000 0000c <<= 4;// c = 1111 1111 1111 1111 1111 1111 1111 0000int e = 2;// e = 0000 0000 0000 0000 0000 0000 0000 0010e = ~e | 6;// e = 1111 1111 1111 1111 1111 1111 1111 1101 | // 0000 0000 0000 0000 0000 0000 0000 0110// = 1111 1111 1111 1111 1111 1111 1111 1111d = (d & 0xff) + 0x2022;// d = 1111 1111 0000 0000 & 0000 0000 1111 1111 + 0x2022 = 0x2022printf("a=0x%hx\tb=0x%x\td=0x%hx\te=0x%x\n", a, b, d, e);// a = 0xfffe, b = 0xffffffff, d = 0x2022, e = 0xffffffffprintf("c=Ox%hhx\t\n", (signed char)c);// (signed char)c = 1111 0000 = 0xf0
}
7. 指针和数组的恩怨情仇
int main(void) {int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};int(*b)[3] = a;++b;b[1][1] = 10;int *ptr = (int *)(&a + 1);printf("%d %d %d \n", a[2][1], **(a + 1), *(ptr - 1));}
int main(void) {int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};int(*b)[3] = a;++b;b[1][1] = 10;int *ptr = (int *)(&a + 1);// *ptr = *(&a + sizeof(a)) = b// **(a + 1) = **(*(&a[0] + sizeof(a[0]))) = a[1][0]// *(ptr - 1) = *(&a + sizeof(a) - sizeof(*ptr)) = a[3][3]printf("%d %d %d \n", a[2][1], **(a + 1), *(ptr - 1));}
8. 移形换位之术
下面有
a
、b
、c
三个变量和4个相似的函数。
- 你能说出使用这三个变量的值或地址作为参数分别调用这5个函数,在语法上是否正确吗?
- 请找出下面的代码中的错误。
const int
和int const
是否有区别?如果有区别,请谈谈他们的区别。const int *
和int const *
是否有区别?如果有区别,请谈谈他们的区别。
int a = 1;
int const b = 2;
const int c = 3;
void funco(int n) {n += 1;n = a;
}
void func1(int *n) {*n += 1;n = &a;
}
void func2(const int *n) {*n += 1;n = &a;
}
void func3(int *const n) {*n += 1;n = &a;
}
void func4(const int *const n) {*n += 1;n = &a;
}
int a = 1;
int const b = 2;
const int c = 3;
void func0(int n) {// a formal parameter nn += 1;n = a;
}
void func1(int *n) {// a pointer n*n += 1;n = &a;
}
void func2(const int *n) {// a const int pointer to n// *n is a const, unchangeable*n += 1;n = &a;
}
void func3(int *const n) {// an int pointer to const n*n += 1;// n is a const, unchangeablen = &a;
}
void func4(const int *const n) {// a const int pointer to const n// *n is a const, unchangeable*n += 1;// n is a const, unchangeablen = &a;
}
9. 听说翻转字母大小写不影响英文的阅读?
请编写
convert
函数用来将作为参数的字符串中的大写字母转换为小写字母,将小写字母转换为大写字母。返回转换完成得到的新字符串。
char *convert(const char *s);
int main(void) {char *str = "XiyouLinux Group 2022";char *temp = convert(str);puts(temp);
}
#include <stdio.h>
#include <string.h>
char *convert(const char *s)
{int len = strlen(s);char *result = malloc(sizeof(char) * (len + 1));strcpy(result, s);for (int i = 0; i < len; i++){if (result[i] >= 'A' && result[i] <= 'Z')result[i] += 32;else if (result[i] >= 'a' && result[i] <= 'z')result[i] -= 32;}return result;
}
int main(void)
{char *str = "XiyouLinux Group 2022";char *temp = convert(str);puts(temp);
}
10. 交换礼物的方式
- 请判断下面的三种
Swap
的正误,分别分析他们的优缺点。- 你知道这里的
do {...} while(0)
的作用吗?- 你还有其他的方式实现
Swap
功能吗?
#define Swap1(a, b, t) \do { \t = a; \a = b; \b = t; \} while (0)
#define Swap2(a, b) \do { \int t = a; \a = b; \b = t; \} while (0)
void Swap3(int a, int b) {int t = a;a = b;b = t;
}
Swap1()
和Swap2()
通过宏定义实现两数交换,do {...} while(0)
可以用代码块花括号{...}
替代,目的是防止宏替换后语句不在同一代码块内。Swap3()
错误,交换形参的值并不能改变实参。Swap4()
利用指针来实现。
void Swap4(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}
11. 据说有个东西叫参数
你知道
argc
和argv
的含义吗?请解释下面的程序。你能在不使用argc
的前提下,完成对argv
的遍历吗?
int main(int argc, char *argv[]) {printf("argc = %d\n", argc);for (int i = 0; i < argc; i++)printf("%s\n", argv[i]);
}
argc
指argument count,即参数计数器,argv
指argument vector,即参数数组。程序在运行时传入的第一个参数就是程序的启动路径/文件名,因此argc
最小为1
。在循环中,整型argc
会自增到溢出,然后打印argv[0]
即程序路径。
不使用argc
遍历argv
的方法:
#include <stdio.h>
int main() {_CRTIMP extern int __argc;_CRTIMP extern char **__argv;printf("argc = %d\n", __argc);for (int i = 0; i < __argc; i++)printf("%s\n", __argv[i]);
}
12. 人去楼空
这段代码有是否存在错误?谈一谈静态变量与其他变量的异同。
int *func1(void) {static int n = 0;n = 1;return &n;
}
int *func2(void) {int *p = (int *)malloc(sizeof(int));*p = 3;return p;
}
int *func3(void) {int n = 4;return &n;
}
int main(void) {*func1() = 4;*func2() = 5;*func3() = 6;
}
*func3()
返回的是局部变量,在外部赋值时此局部变量已被抛弃,成为了野指针。
13. 奇怪的输出
int main(void) {int data[] = {0x636c6557, 0x20656d6f, 0x78206f74,0x756f7969, 0x6e694c20, 0x67207875,0x70756f72, 0x32303220, 0x00000a31};puts((const char*)data);
}
#include <stdio.h>
int main(void) {// c l e W e m o x o tint data[] = {0x636c6557, 0x20656d6f, 0x78206f74,// u o y i n i L g x u0x756f7969, 0x6e694c20, 0x67207875,// p u o r 2 0 2 \0 10x70756f72, 0x32303220, 0x00000a31};// unsigned char data[34] = {// 0x57, 0x65, 0x6C, 0x63, 0x6F, 0x6D, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x78,// 0x69, 0x79, 0x6F, 0x75, 0x20, 0x4C, 0x69, 0x6E, 0x75, 0x78, 0x20, 0x67,// 0x72, 0x6F, 0x75, 0x70, 0x20, 0x32, 0x30, 0x32, 0x31, 0x00};// }puts((const char *)data);
}
14. 请谈谈对从「C语言文件到可执行文件」的过程的理解
编辑:创建和修改C程序的源代码
编译:将源代码转换为机器语言
链接:链接器将源代码由编译器产生的各种模块组合起来,再从C语言提供的程序库中添加必要的代码模块,将它们组成一个可执行的文件
执行:运行程序
15. (选做) 堆和栈
你了解程序中的栈和堆吗?它们在使用上有什么区别呢?请简要说明。
16. (选做) 多文件
一个程序在不使用任何头文件的情况下,如何使用另一个文件中的函数。
17. (选做) GNU/Linux
与文件
- 你知道如何在
GNU/Linux
下如何使用命令行创建文件与文件夹吗?- 你知道
GNU/Linux
下的命令ls 的每一列的含义吗?- 你知道
GNU/Linux
下文件的访问时间、修改时间、创建时间如何查看吗?并简单说说他们的区别。
恭喜你做完了整套面试题,快来参加西邮Linux兴趣小组的面试吧!
西邮 Linux兴趣小组面试时间:
2021年10月25日至2021年10月31日晚8点。
听说面试来的早一点更能获得学长学姐的好感哦。我们在FZ103等你!
西邮Linux兴趣小组2021纳新面试题题解相关推荐
- 西邮Linux兴趣小组2021纳新面试题
#include<stdio.h> #include<string.h> int main(void) {char s[]="I love Linux\0\0\0&q ...
- 西邮Linux兴趣小组2022纳新面试题题解
本题目只作为Xiyou Linux兴趣小组2022纳新面试的有限参考. 为节省版面,本试题的程序源码省去了#include指令. 本试题中的程序源码仅用于考察C语言基础,不应当作为C语言「代码风格」的 ...
- 西邮Linux兴趣小组2021纳新试题
1.大小和长度竟然不是一个意思, sizeof()和strlen()有什么异同之处? 他们对于不同参数的结果有什么不同?请试举例子说明. int main(void) { char s[] = &qu ...
- 西邮Linux兴趣小组2021纳新试题②
1. 结果:127 -128 signed char的范围是-128~127 unsigned char的范围是0~256 计算a-ch是把ch转换成整数,而输出ch是进行了类型转换为char类型,1 ...
- 西邮linux兴趣小组网络,西邮Linux兴趣小组2012纳新笔试题
这是我们西邮Linux兴趣小组2012的纳新笔试题,对于大一的学生,出得有难度哦,个人感觉比腾讯实习生的笔试题出的有水平. 西邮Linux兴趣小组纳新试题 姓名: ...
- 西邮Linux兴趣小组2017纳新免试题揭秘
声明 今年的免试题按照关卡顺序依次是由小组15级成员何攀.楚东方.宫展京.杜肖孟.王一妃同学精心准备的(鼓掌),每个人总结了一下自己负责关卡的解法,我这里整理了一下,给出一套完整的免试题详解,免试题通 ...
- 西邮 Linux 兴趣小组 2021 纳新试题
1. 请试着解释其输出 int main(int argc , char *argv[]) {unsigned char a = 255;char ch = 128;a -= ch;printf(&q ...
- [c语言]西邮Linux兴趣小组2020纳新面试题
一.运行下面的代码,输出结果是什么,解释原因. int i; int main(int argc, char *argv[]) {i--;if (i > sizeof(i)){printf(&q ...
- 西邮linux兴趣小组2014纳新免试题(四)
[第四关] 题目 http://findakey.sinaapp.com/ Example:String1:FFFF8 5080D D0807 9CBFC E4A04 24BC6 6C840 49B5 ...
最新文章
- docker load 出错 open /var/lib/docker/tmp/docker-import-837327978/bin/json: no such file or directory
- 【转载】gdi+ 内存泄漏
- rocketmq python 一个进程订阅多个topic_玩转不同业务场景,这些RabbitMQ特性会是得力助攻...
- android 文件下载 超简单
- M元上升子序列【树状数组+dp】
- Andrew Ng 深度学习笔记-01-week2-课程
- python求不规则图形面积_python 微积分之---黎曼和
- npm install引起的项目崩溃(This is probably not a problem with npm,there is likely additional logging outp)
- TCP/IP原理 (四) IP编址
- guava 对集合的支持
- Tensorflow:可视化学习TensorBoard
- 生态丨人大金仓与超图集团共商战略新发展、共营和谐新生态!
- JS炫彩动画效果的文字特效
- Crystal Xcelsius 2008 使用Excel XML映射链接
- 网站url监控脚本(告警)
- 电路基础学习笔记5:实验验证电压源与电流源的等效变换
- Flutter 错误解决Building with plugins requires symlink support.
- 斗图表情包爬虫(基于多线程)
- 【数据结构】链表 - Go 语言实现
- 微信小程序:更改页面背景颜色