西邮linux兴趣小组2023面试题
零、鼠鼠要被祸害了
用10位二进制编码为老鼠编号,每一瓶水代表一位上的数值,定为1,e.g.最后一位为一的喝一瓶,倒数第二位为1的喝一瓶…
最后会定位出有毒之水的编号。
算是一种2*10的坐标图确定坐标吧
自然界最容易找的就是0与1的状态,例如生与死。
一、输出自己的名字
按照函数要求输入自己的姓名试试~
char *welcome() {
// 请你返回自己的姓名
}
int main(void) {
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
return 0;
}
此处考察的是函数的返回值,当我们在定义函数时设置一个有自己名字的数组,并在函数运行结束时返回这个数组的地址我们就可以实现输出,因为这个函数的返回值被定义为指针类型,在主函数里我们将这个数组的地址赋值给一个字符指针a,这样输出a的时候相当于输出整个数组,便可以输出我们的名字。
e.g
#include<stdio.h>
char *welcome() {
char *arr="erthern";
return arr;
}
int main(void) {
char *a = welcome();
printf("Hi, 我相信 %s 可以面试成功!\n", a);
printf("%d",a);
return 0;
}
//输出
Hi, 我相信 erthern 可以面试成功!
二、欢迎来到 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);
}
ptr0和ptr1是两个字符数组的指针,对二者解引用后均为数组首元素W故开始if条件下的语句。
这里考察printf函数返回值,其返回值是格式化输出的字符串长度即""内替换后所有内容视为字符串的长度。
diff是两个地址的差值。
//输出
Hello, Linux Group - 2023
Pointer Difference: 1431667044
三、一切都翻番了吗
① 请尝试解释一下程序的输出。
② 请谈谈对 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)); }
//输出
7 8 2
0
4 5
输出:arr是一个字符数组,具体如下:
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));//第一个是对整个函数取地址又解引用,输出整个数组的内存大小,第二个是数组第一个元素的地址,第三个是short类型数据的大小为两个字节
printf("%d\n", sprintf(str, "0x%x", num) == num);//第一步是将num的十六进制数追加写入到str字符数组里,返回值是写入的字符总数即长度,不包括\0,然后与num判断大小,不相等故输出0
printf("%zu\t%zu\n", strlen(&str[0] + 1), strlen(arr + 0)); }//str被写入ox加三位(因为出short类型num转换成十六进制只有三位),第一个取str首元素地址的下一个元素的地址开始计算,只有4的长度,第二个是中间有一个\0,只读取到前一个元素,所以是5.
sizeof:变量占用内存的空间大小
strlen:求字符串长度
sprintf:将格式化输出内容转而写入字符数组,返回写入长度
四、奇怪的输出
程序的输出结果是什么?解释一下为什么出现该结果吧~
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);
}
这里考察的是位运算
异或可视为不进位加法
&可用于取模运算,比%快,少了数据转换的复杂度
五、乍一看就不想看的函数
这道题的考察点有三个,一为函数的定义,二为逻辑运算符,三为数据在内存的储存形式
此函数的功用为实现两个数据的加法。
这个 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)));
}
(1)&为按为与,<<是向左缩进,^按位异或
(2)逻辑运算中参与运算的数据是二进制补码的形式
(3)采用递归思想
即a^b后,0+0=0,1+1=0,0+1=1
同时,a&b将1+1得到的进位1提取,<<1提前一位
当没有进位时便得到了a+b
六、自定义过滤
请实现 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;
}
要自定义过滤数组,需要定义filter()函数。
此处涉及的知识点:1.函数的定义
2.数据类型的定义
过程:
1、定义一个函数指针predicate作为筛选标准
2、为输出的数组提供内存
3、将符合的数据输出
如下是代码补完:
#include<stdio.h>
#include<stdlib.h>
typedef int (*Predicate)(int);
int *filter(int *array,int length,Predicate predicate,int *resultlength){
int i=0,t=0;
int *p=(int*)malloc(sizeof(int)*length);
for(i;i<length;i++){
if(predicate(array[i])) {
p[t]=array[i];
t++;
}
}
*resultlength=t;
return p;
}
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;
}
七、静态
① 如何理解关键字 static?
② static 与变量结合后有什么作用?
③ static 与函数结合后有什么作用?
④ static 与指针结合后有什么作用?
⑤ static 如何影响内存分配?
修饰变量时将变量从栈区的变量移到静态区,使其生命周期延续到整个程序(比如在循环内定义的变量值可以脱离循环使用)。
若修饰全局变量或者函数则会将其外部属性转换成内部属性。
八、救命!指针!
数组指针是什么?指针数组是什么?函数指针呢?用自己的话说出来更好哦,下面数据类
型的含义都是什么呢?
int (*p)[10];
const int* p[10];
int (*f1(int))(int*, int);
1、数组指针是指向数组的指针,第一个就是数组指针,定义了一个int类型指针p指向一个有十个元素的数组,不知数组名
2、指针数组是存储指针变量的数组,第二个将整个数组p定义成了指针,const修饰后都指向常量
3、函数指针是指向函数体的指针,f1指针指向一个两个int类型形参的指针
九、咋不循环了
#include<stdio.h>
#include<stdlib.h>
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;
}
[1]
i=0,j=1,k=2
argc是命令行参数的技术器,至少为1,不断自增后溢出再增到0,退出循环
先计算j和k的或,虽然j=0但是k不等于0,故为真,&&前面i也不为0,后缀++要语句运行结束才计算。
十、到底是不是TWO
#include<stdio.h>
#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%d\n",nums,magic_cal(nums,2));
}
nums的生命周期只持续在if判断里面,出来还是1
且当多个++nums相乘时运算顺序会产生混乱
不知道每一个nums 的值是多少
十一、克隆困境
试着运行一下程序,为什么会出现这样的结果?
直接将 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;
}
直接赋值是将s2的地址直接赋值给s1因此两个都输出s2的数值
此时释放的内存只有s2的name,造成了s1.name的内存泄露
十二、你好我是内存
作为一名合格的 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);
}//将arr的指针与结构体匹配从string的地址开始翻译,00为止
此处考察的是内存储存的大小端模式,思路参见2022年纳新题第十二题
//输出
Welcome to XUPT , welcome to Xiyou Linux Group [2023]