西邮Linux兴趣小组2023纳新面试题
0.鼠鼠我啊,要被祸害了
- Q:
有 1000 瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水,24 小时后就会准时死亡。
至少要多少只小白鼠才能在 24 小时内鉴别出哪瓶水有毒? - A:
将1000瓶水分别用二进制数表示,最多使用10位数,取10个空瓶子作为那10位,将对应位为1的水加入空瓶,最后取十只小鼠分别喝十瓶水,最后以小鼠的死亡给瓶子取值1,其它为0,可得毒水对应的二进制数。
1.先预测一下~
- Q:
按照函数要求输入自己的姓名试试~
char *welcome() {
// 请你返回自己的姓名
}
int main(void) {
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0;
}
- A:
char *welcome()
{
static char a[]="自己的姓名";
return a;
}
2.欢迎来到 Linux 兴趣小组
- Q:
int main(void) {
char *ptr0 = "Welcome to Xiyou Linux!";
char ptr1[] = "Welcome to Xiyou Linux!";
if (*ptr0 == *ptr1) {
printf("%d\n", printf("Hello, Linux Group - 2%d", printf("")));
}
int diff = ptr0 - ptr1;
printf("Pointer Difference: %d\n", diff);
}
- A:
int main(void) {
char *ptr0 = "Welcome to Xiyou Linux!";
//创建指针,指向字符串常量
char ptr1[] = "Welcome to Xiyou Linux!";
//创建数组
if (*ptr0 == *ptr1) {
printf("%d\n", printf("Hello, Linux Group - 2%d", printf("")));
}
//第一个%d=0;第二个%d=23
int diff = ptr0 - ptr1;
//diff=两地址差
printf("Pointer Difference: %d\n", diff);
}
3.一切都翻倍了吗
- Q:
① 请尝试解释一下程序的输出。
② 请谈谈对 sizeof()和 strlen()的理解吧。
③ 什么是 sprintf(),它的参数以及返回值又是什么呢?
int main(void) {
char arr[] = {'L', 'i', 'n', 'u', 'x', '\0', '!'}, str[20];
short num = 520;
int num2 = 1314;
printf("%zu\t%zu\t%zu\n", sizeof(*&arr), sizeof(arr + 0),
sizeof(num = num2 + 4));
printf("%d\n", sprintf(str, "0x%x", num) == num);
printf("%zu\t%zu\n", strlen(&str[0] + 1), strlen(arr + 0));
}
- A:
①
int main(void) {
char arr[] = {'L', 'i', 'n', 'u', 'x', '\0', '!'}, str[20];
short num = 520;
int num2 = 1314;
printf("%zu\t%zu\t%zu\n", sizeof(*&arr), sizeof(arr + 0),
sizeof(num = num2 + 4));
//sizeof(*&arr)=sizeof(arr)=7;sizeof(arr+0)=sizeof(long long)=8;sizeof(num=num2+4)=sizeof(short)=2,不对表达式求值
printf("%d\n", sprintf(str, "0x%x", num) == num);
//将字符串”0x522“写入str,“sprintf(str, "0x%x", num)==num”结果=0=%d
printf("%zu\t%zu\n", strlen(&str[0] + 1), strlen(arr + 0));
//strlen(&str[0]+1)=strlen(str+1)=从str[1]到'\0'(不包括)的字符个数=4;strlen(arr+0)=5
}
② sizeof()
对应数据类型在内存中所占用的字节数;
strlen()
显示字符串的长度,即在`\0`前的字符个数。
③ sprintf()为输出函数,第一个参数为指向字符数组的指针,其它为格式化字符串;返回值为写入的字符总数,失败返回-1。
4.奇怪的输出
- Q:
程序的输出结果是什么?解释一下为什么出现该结果吧~
int main(void) {
char a = 64 & 127;
char b = 64 ^ 127;
char c = -64 >> 6;
char ch = a + b - c;
printf("a = %d b = %d c = %d\n", a, b, c);
printf("ch = %d\n", ch);
}
- A:
按顺序(补码):
a=00100000;
b=00011111;
c=11111111;
ch=11000000;
输出:a=64,b=63,c=-1,ch=-128
5.乍一看就不想看的函数
- Q:
“人们常说互联网凛冬已至,要提高自己的竞争力,可我怎么卷都卷不过别人,只好用一些奇技淫
巧让我的代码变得高深莫测。”
这个 func()函数的功能是什么?是如何实现的?
int func(int a, int b) {
if (!a) return b;
return func((a & b) << 1, a ^ b);
}
int main(void) {
int a = 4, b = 9, c = -7;
printf("%d\n", func(a, func(b, c)));
}
- A:
功能:求两数的和;
实现:(a & b) << 1
表示两数相加的进位a ^ b
表示两数相加的原位。
函数通过递归不断相加每次相加得到的进位和原位,没有进位时返回值。
6.自定义过滤
- Q:
请实现 filter()函数:过滤满足条件的数组元素。
提示:使用函数指针作为函数参数并且你需要为新数组分配空间。
typedef int (*Predicate)(int);
int *filter(int *array, int length, Predicate predicate,
int *resultLength); /*补全函数*/
int isPositive(int num) { return num > 0; }
int main(void) {
int array[] = {-3, -2, -1, 0, 1, 2, 3, 4, 5, 6};
int length = sizeof(array) / sizeof(array[0]);
int resultLength;
int *filteredNumbers = filter(array, length, isPositive,
&resultLength);
for (int i = 0; i < resultLength; i++) {
printf("%d ", filteredNumbers[i]);
}
printf("\n");
free(filteredNumbers);
return 0;
}
- A:
int *filter(int *array, int length, Predicate predicate,int *resultLength)
{
int s=0;
for(int c=0;c<length;c++)
{
if(predicate(array[c]))s++;
}
*resultLength=s-1;
int *fi=(int*)malloc(sizeof(int)*s);
s=0;
for(int c=0;c<length;c++)
{
if(predicate(array[c]))
{
fi[s]=array[c];
s++;
}
}
return fi;
}
7.静…态…
- Q:
① 如何理解关键字 static?
② static 与变量结合后有什么作用?
③ static 与函数结合后有什么作用?
④ static 与指针结合后有什么作用?
⑤ static 如何影响内存分配? - A:
① static用来修饰变量的数据类型
② 与局部变量结合,使变量具有静态存储期;与全局变量结合,使其具有内部链接的文件作用域
③ 使函数成为静态函数
④ 使指针变量具有静态存储期
⑤ static修饰的变量在程序运行时分配内存,结束时释放
8.救命!指针
- Q:
数组指针是什么?指针数组是什么?函数指针呢?用自己的话说出来更好哦,下面数据类
型的含义都是什么呢?
int (*p)[10];
const int* p[10];
int (*f1(int))(int*, int);
- A:
数组指针:指向数组的指针
指针数组:数组元素为指针的数组
函数指针:指向函数的指针,可通过指针使用函数
int (*p)[10];//指向含10个int元素的数组的指针
const int* p[10];//含有10个指向const数组的指针的数组
int (*f1(int))(int*, int);//返回值为指向返回值为int、参数为(int*,int)类型的函数的指针的函数声明
9.咋不循环了
- Q:
程序直接运行,输出的内容是什么意思?
int main(int argc, char* argv[]) {
printf("[%d]\n", argc);
while (argc) {
++argc;
}
int i = -1, j = argc, k = 1;
i++ && j++ || k++;
printf("i = %d, j = %d, k = %d\n", i, j, k);
return EXIT_SUCCESS;
}
- A:
当argc溢出时,从最小值开始继续循环,到0时退出循环;i++ && j++ || k++;
增加i和j,因为表达式i++ && j++
的值为0,继续执行增加k;最终i=0,j=1,k=2
10.到底是不是 TWO
- Q:
#define CAL(a) a * a * a
#define MAGIC_CAL(a, b) CAL(a) + CAL(b)
int main(void) {
int nums = 1;
if(16 / CAL(2) == 2) {
printf("I'm TWO(ノ>ω<)ノ\n");
} else {
int nums = MAGIC_CAL(++nums, 2);
}
printf("%d\n", nums);
}
- A:
预处理后
int main(void) {
int nums = 1;
if(16 /2*2*2 == 2) //表达式为0
{
printf("I'm TWO(ノ>ω<)ノ\n");
} else {
int nums = ++nums*++nums*++nums+2*2*2;//块内创建nums并运算,出块后消失,块外nums依旧为1
}
printf("%d\n", nums);//输出1
}
11.克隆困境
- Q:
试着运行一下程序,为什么会出现这样的结果?
直接将 s2 赋值给 s1 会出现哪些问题,应该如何解决?请写出相应代码。
struct Student {
char *name;
int age;
};
void initializeStudent(struct Student *student, const char *name,int age)
{
student->name = (char *)malloc(strlen(name) + 1);
strcpy(student->name, name);
student->age = age;
}
int main(void) {
struct Student s1, s2;
initializeStudent(&s1, "Tom", 18);
initializeStudent(&s2, "Jerry", 28);
s1 = s2;
printf("s1 的姓名: %s 年龄: %d\n", s1.name, s1.age);
printf("s2 的姓名: %s 年龄: %d\n", s2.name, s2.age);
free(s1.name);
free(s2.name);
return 0;
}
- A:
使s1中的指针也指向s2指向的内存空间,丢失了s1原本指向的内存空间,使其无法正确释放(free)
解决方法:令以下代码取代s1 = s2;
strcpy(s1.name,s2.name);
s1.age=s2.age;
12.你好,我是内存
- Q:
作为一名合格的 C-Coder,一定对内存很敏感吧~来尝试理解这个程序吧!
struct structure {
int foo;
union {
int integer;
char string[11];
void *pointer;
} node;
short bar;
long long baz;
int array[7];
};
int main(void) {
int arr[] = {0x590ff23c, 0x2fbc5a4d, 0x636c6557, 0x20656d6f,
0x58206f74, 0x20545055, 0x6577202c, 0x6d6f636c,
0x6f742065, 0x79695820, 0x4c20756f, 0x78756e69,
0x6f724720, 0x5b207075, 0x33323032, 0x7825005d,
0x636c6557, 0x64fd6d1d};
printf("%s\n", ((struct structure *)arr)->node.string);
}
- A:
struct structure {
int foo;//占4字节
union {
int integer;
char string[11];
void *pointer;
} node;//偏移4字节,占16字节
short bar;
long long baz;
int array[7];
};
int main(void) {
int arr[] = {0x590ff23c, 0x2fbc5a4d, 0x636c6557, 0x20656d6f,
0x58206f74, 0x20545055, 0x6577202c, 0x6d6f636c,
0x6f742065, 0x79695820, 0x4c20756f, 0x78756e69,
0x6f724720, 0x5b207075, 0x33323032, 0x7825005d,
0x636c6557, 0x64fd6d1d};
printf("%s\n", ((struct structure *)arr)->node.string);
//跳过前面的8个字节,按照char类型逐个读取字符,因为计算机为小端存储,所以读取顺序为
//57 65 6c 63 6f 6d 65 20 74 6f 20 58 55 50 54 20 2c 20 77 65 6c 63
//6f 6d 65 20 74 6f 20 58 69 79 6f 75 20 4c 69 6e 75 78 20 47 72 6f
//75 70 20 5b 32 30 32 33 5d 00(不包括)
//即Welcome to XUPT , welcome to Xiyou Linux Group [2023]
}
13.GNU/Linux (选做)
- Q:
注:嘿!你或许对 Linux 命令不是很熟悉,甚至你没听说过 Linux。但别担心,这是选做题,了解
Linux 是加分项,但不了解也不扣分哦!
你知道 cd 命令的用法与 / . ~ 这些符号的含义吗?
请问你还懂得哪些与 GNU/Linux 相关的知识呢~ - A: