西邮Linux兴趣小组 2023 纳新面试题题解

Copyright © 202 3 西邮Linux兴趣小组, All Rights Reserved. 本试题使用采用知识共享署名-非商业性使用-相同方式共享4.0 国际许可协议(CC BY-NC-SA 4.0)进行许可。

西邮Linux兴趣小组 2023 纳新面试题

解释①本题目只作为西邮Linux兴趣小组 2023 纳新面试的有限参考。
②为节省版面,本试题的程序源码省去了#include指令。
③本试题中的程序源码仅用于考察C语言基础,不应当作为C语言「代码风格」的范例。
④所有题目编译并运行于x86_64 GNU/Linux环境。

0.鼠鼠我啊,要被祸害了

有 1000 瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水, 24 小时后就会准时死亡。

至少要多少只小白鼠才能在 24 小时内鉴别出哪瓶水有毒?

10瓶。

  • 1000 可以用二进制表示为 10 位,1和0就可以表示死亡情况( 2^9 = 512 ),不够.2^10 = 1024 ,够
    所以每一瓶水都可以标一个二进制的编号,2的十次方是1024
  • 小白鼠按照编号,喝水.1表示喝了0表示没喝
    24小时之后,根据10只小鼠的死亡情况可以得出喝了or没喝–即得出编码,then根据瓶子的编码判断哪瓶水有毒

1.先预测一下~

按照函数要求输入自己的姓名试试~

char *welcome() {
// 请你返回自己的姓名
}
int main(void) {
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0 ;
}
  • 在welcome函数里面,然而return自己的姓名即可

(在使用 %s 打印字符串时,不需要解引用指针 a,因为 %s 期望的是一个指向字符的指针,而不是字符本身)

char *welcome() {
return xxx;
}
int main(void) {
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0;
}

2.欢迎来到Linux兴趣小组

有趣的输出,为什么会这样子呢~

解释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);
}
  • if语句比较了两个字符数组的首元素值,W=W,所以执行语句
  • printf函数嵌套,先执行括号里的,所以最里面的括号里的先执行,
    什么也不打印,返回0,
  • 然后中层的printf打印双引号里的字符并将占位符%d替换为里面函数的返回值0。
  • 最后,最外面的printf函数打印中间函数的返回值23。

最后结果就为“Hello, LinuxGroup - 2023"。

最后一个printf打印两个地址之差,由于不指向同一个数组,是未定义行为,会随机输出值.

在c语言环境中,嵌套的printf函数是从内到外调用的顺序来执行,这样保证在进行格式化输出的时候,所有参数都已经计算完毕。

3.一切都翻倍了吗

①请尝试解释一下程序的输出。

②请谈谈对 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 ));
}

sizeof运算符计算占空间字节数,strlen函数计算字符串长度且不计\0
sizeof是运算符,strlen是函数,sizeof 参数可以是数据类型、变量,streln接收的参数是字符指针
程序输出:

7       8       2
0
4       5

arr大多数情况下会退化成指向数组第一个元素的指针,但在特殊情况下,如sizeof和取地址操作,会保持原本的数组类型

  1. &arr代表整个数组的地址,*&arr表示再解引用,得到整个数组arr,所以sizeof(arr)是7
    在 C 语言中,如果用字符数组初始化的方式定义 char arr[] = {‘L’, ‘i’, ‘n’, ‘u’, ‘x’, ‘\0’, ‘!’},编译器不会自动在末尾添加 ‘\0’,所以是7个字节,输出7
  2. 在表达式中,arr大多是情况会退化为指向数组首元素的指针,所以sizeif(arr+0)中arr表示指针,指针在64系统中,占用字节数为8
  3. 第三个打印里面整个表达式的结果占字节数,结果num是short int 类型,所以为2。
    第二行printf函数打印sprintf函数的返回值与num相等是否为真的值。
    sprintf函数至少有两个参数,若有三个,则第二个参数中有转换说明,这个sprintf函数将num的值拷贝到str数组里,然后返回拷贝的字符数,为3,与520不相等,所以printf函数打印0;
  4. 第三行,strlen函数与sizeof运算符不同的是,strlen函数接收地址,printf函数第一个参数为str从第二个元素开始计算的字符串长度,为4,第二个参数为从第一个元素开始,为5。

4.奇怪的输出

程序的输出结果是什么?解释一下为什么出现该结果吧~

解释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);
}
  • &运算符是同位都为1才是1其他情况都是0
  • ^运算符是同位相同则为1,不同则为0
  • 右移运算符,各二进位全部右移若干位,无符号数高位补0,负数高位补1

位运算,第一行为a,b,c三个位运算之后的值,分别为64,63,-1,

  • char c = -64 >> 6;
    -64 的二进制表示为补码。在 8 位系统中,-64 是 11000000。

右移 6 位会将 11000000 变为 11111111(在有符号右移时,符号位填充)。
因此,c 的值为 -1(即 11111111) 在补码中表示

  • ch:因为是char类型,它的符号位是第八位,127原码为01111111,1的原码为00000001,相加后为10000000,为-128的原码,所以答案为-128

5.乍一看就不想看的函数

“人们常说互联网凛冬已至,要提高自己的竞争力,可我怎么卷都卷不过别人,只好用一些奇技淫巧让我的代码变得高深莫测。”

这个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)));
}

打印出的值为6。

  • func函数的功能是将传入的两个参数相加并返回相加结果

if (!a) return b;:如果 a 为 0,直接返回 b。这是因为任何数加 0 等于它本身。
如果a不是0,
通过函数递归和位运算使得倒数第二次函数调用时第一个参数为零,第二个参数为初始两参数和。在最后一次调用里返回两初始参数和。
该函数涉及使用位运算实现加法,递归情况:
eturn func((a & b) << 1, a ^ b);:
a & b:计算 a 和 b 的位与运算,得到的结果是所有相同位为 1 的部分(即进位)。
(a & b) << 1:将进位左移一位,以便在下一次递归中加到正确的位置。
a ^ b:计算 a 和 b 的位异或运算,得到不考虑进位的结果。
func((a & b) << 1, a ^ b):递归调用 func,将进位和当前的和作为新的参

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值