西邮Linux兴趣小组2022年纳新面试题解析

0.
在这里插入图片描述

结果:3000多位
1024约等于1000,210000=(210)1000=(103)1000,所以就是3000多位。
1.
在这里插入图片描述

结果:Xiyou Linux Group - 2022
①3+2=5<2为假为0,3+2>2为真为1,0>1为假,所以if条件不成立
②执行else后面的语句,printf还可以嵌套?
printf()函数的返回值为被打印的字符个数。
注意:printf()打印的单引号,空格,英文句号,未省略的换行符都是占一个打印字符数的。
那么scanf是否也有返回值呢?scanf()的返回成功读取的项数。scanf()需要读取一个数字如果用户输入一个非数值字符串,scanf()会返回0,如果检测到文件末尾,会返回EOF。
2.
在这里插入图片描述

结果:0 0 12 8 1 11 11
①"=="是判断相等的运算符,明显数组和指针的地址不一样,所以是0。
strcmp(p0,p2)函数是比较字符串是否相等,是用ASCII码值来比较的,若相等则返回0,p0大于p2则返回正整数,p0小于p2则返回负整数。本题相等则返回0。
sizeof是运算符,计算的是你使用的操作数所占的空间字节大小,包括’\0’,而strlen是函数,计算的是字符串的长度,不包括’\0’
所以sizeof(p0)=12;p1是一个指针,在32位编译器上是4位,在64位编译器上是8位,sizeof(p1)=8;’*p2’=‘H’,char类型占一个字节,sizeof(p2)=1.
strlen(p0),strlen(p1)都是11.
3.
在这里插入图片描述
结果:不确定 2 3
大家想想为什么会不确定呢?让我们共同来谈谈全局变量和局部变量以及它们的生命周期吧!
全局变量:定义在函数体内部的变量,作用域(确定变量可以在哪里使用)仅限于函数体内部,离开函数体无效。
它的生命周期是:进作用域,生命周期开始,出作用域生命周期结束。
局部变量:所有函数外部定义的变量,它的作用域是整个程序。它的生命周期是:整个程序。
需要 注意的是同名时局部变量优先!!!
第一个a未初始化,a是啥,不认识!系统会自动赋值,所以不确定。
第二个a是test里定义的a等于2。
第三个a是用的全局变量a等于3。
4.
在这里插入图片描述

结果:20 32

结构体struct
各成员各自拥有自己的内存,遵循内存对齐原则
1.第一个成员在结构体变量偏移量为0的地址处
2.其他成员变量要对齐到对齐数的整数倍的地址处
对齐数=编译器默认的一个对齐数与该成员大小中的较小值。Linux中的默认值为4.
3.结构体总大小为最大对齐数的整数倍。

联合体union
各成员共用一块内存空间,并且同时只有一个成员可以得到这块内存的使用权,各变量共用一个内存的首地址。
1.一个union变量的总长度至少能容纳最大的成员变量
2.满足所有成员变量类型大小的整数倍

代码UNION中至少容纳最大i[5]=20字节,同时变量类型最大值是整数倍,因而sizeof(UNION)=20
代码中STRUCT中int占4个字节,而UNION里最大数据类型是占4个字节,所以直接占用接下来的20个字节,是24,double占用8个字节,24是8的整数倍,然后直接占用接下来的8个字节,是32,而32是8的整数倍,因而sizeof(STRUCT)=32。
5.
在这里插入图片描述

结果:56 0 254 48 OX4
**位运算是用补码进行运算的

按位运算符
1.按位取反:~
一元运算符~把1变成0,把0变成1.例如:
~(10101101) 的结果是(01010010)
2.按位与:&
二元运算符&逐位比较两个运算对象,当相应位都是1时,结果才是1,否则为0(只要有0就是0)
例如:(10101101)&(11101010)的结果是(10101000)
3.按位或:|
二元运算符|逐位比较两个运算对象,当对应位都是0时,结果才是0,否则为1(只要有1就是1)
例如:(10101101)|(11101010)的结果是(11101111)
4.按位异或:^
二元运算符^逐位比较两个运算对象,当对应位相同为0,不同为1

移位运算符
1.左移:<<
移出的高位丢弃,空出的低位补0
例如a<<2 指把a的各二进制位向左移动2位,
若a=6,则0000 0110(十进制是6)左移2位后为0001 1000(十进制是24)
若左移时丢弃的高位不包含1,则每左移一位,相当于给该数乘以2
2.右移:>>
移出的低位丢弃,空出的高位对于无符号数补0,对于有符号数,右移时符号位将随之移动,空出的高位正数补0,负数补1.
若a=6,则0000 0110(十进制是6)右移2位后为0000 0001(十进制是1)
每右移一位,相当于给该数除以2,并去掉小数

6.
在这里插入图片描述
const 限定一个变量不允许改变
①第一组const作用于p,不可修改指针p指向的地址
②第二组和第三组是一种类型,const作用于*p,不可修改指针p指向的值
7.
在这里插入图片描述
1)int ∗ \ast p[10]
[]运算符比 ∗ \ast 运算符优先级高,先和[]结合表明它是一个数组
2)int( ∗ \ast p)[10]
先和 ∗ \ast 结合表明它是一个指针
3)int( ∗ \ast p[3])(int)
说到运算符,下来和大家分享一下比较全的

优先级运算符名称使用形式结合方向说明
1[]数组下标数组名[常量表达式]由左到右
1()圆括号(表达式)/函数名(形参表)由左到右
1.成员选择(对象)对象.成员名由左到右
1->成员选择(指针)对象指针->成员名由左到右
2-负号运算符-表达式由右向左
2~按位取反运算符~表达式由右向左
2++自增运算符++变量名/变量名++由右向左
2自减运算符- -变量名/变量名- -由右向左
2*取值运算符*指针变量由右向左
2&取地址运算符&变量名由右向左
2逻辑非运算符!表达式由右向左
2(类型)强制类型转换(数据类型)表达式由右向左
2sizeof长度运算符sizeof(表达式)由右向左
3/表达式/表达式由左向右
3*表达式*表达式由左向右
3%余数(取模)整形表达式%整形表达式由左向右
4+表达式+表达式由左到右
4-表达式-表达式由左到右
5<<左移变量<<表达式由左到右
5>>右移变量>>表达式由左到右
6>大于表达式>表达式由左到右
6>=大于等于表达式>=表达式由左到右
6<小于表达式<表达式由左到右
6<=小于等于表达式<=表达式由左到右
7==等于表达式==表达式由左到右
7!=不等于表达式!=表达式由左到右
8&按位与表达式&表达式由左到右
9^按位异或表达式^表达式由左到右
10 ∣ \mid 按位或表达式 ∣ \mid 表达式由左到右
11&&逻辑与表达式&&表达式由左向右
12 ∣ \mid ∣ \mid 逻辑或表达式 ∣ \mid ∣ \mid 表达式由左向右
13?:条件运算符表达式1?表达式2:表达式3由右向左三目运算符
14=赋值运算符变量=表达式由右向左
14/=除后赋值变量/=表达式由右向左
14*=乘后赋值变量*=表达式由右向左
14%=取模后赋值变量%=表达式由右向左
14+=加后赋值变量+=表达式由右向左
14-=减后赋值变量-=表达式由右向左
14<<=左移后赋值变量<<=表达式由右向左
14>>=右移后赋值变量>>=表达式由右向左
14&=按位与后赋值变量&=表达式由右向左
14^=按位异或后赋值变量^=表达式由右向左
14 ∣ \mid =按位或后赋值变量 ∣ \mid =表达式由右向左
15逗号运算符表达式,表达式,…从左到右

8.
在这里插入图片描述

时间复杂度:时间复杂度是一个函数(数学里面带有未知数的表达式),而不是去计算算法跑了多少秒,时间与机器有关,没办法计算具体时间,因此算的是基本操作的执行次数,是大概的。使用大O的渐进表示法。
空间复杂度:空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度,也就是额外占取的空间的大小。
稳定性:排序稳定性指的是对于相同数值,在排序前后是否会发生变化
大家会说冒泡排序是稳定的,若条件改成">=或<="会导致算法不稳定。

冒泡排序
时间复杂度:O(n2)
空间复杂度:O(1)
稳定性:稳定

#include<stdio.h>
int main()
{
    int arr[] = { 4,3,2,5,1 };
    int sz = sizeof arr / sizeof arr[0];
    int i,c,t;
    for (i = 0; i < sz; i++)
    {
        c = 0;
        for (int j = 0; j < sz - i - 1; j++)//执行j+1元素不会越界
        {
            if (arr[j] > arr[j + 1])//由小到大排序
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
                c = 1;
            }
        }
            if (c == 0)
                break;//c==0,说明没有发生交换,顺序正确,直接退出循环
    }
    for (i = 0; i < sz; i++)
        printf("%d", arr[i]);
    return 0;
}

桶排序
时间复杂度:O(n)
若待排序列中元素范围跨度较大时,空间占用很大,且不能直接排负数,因数组没有负下标,负数的话可以同比例增加一个数,最后减掉。

#include<stdio.h>
int a[20];//声明数组,用下标做桶的序号
int main()
{
 int n, t;
 scanf("%d", &n);
 for (int i = 1; i <= n; i++)
 {
  scanf("%d", &t);
  a[t]++;//下标为t的元素加一
 }
 for (int i = 1; i <= 10; i++)//遍历整个区间[1,10]
 {
  while (a[i] > 0)
  {
   printf("%d ", i);
   a[i]--;
  }
 }
 return 0;
}

其他还有选择排序,插入排序,归并排序,快速排序,基数排序。

9.
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>


char* convertAndMerge(char words[2][20]);
int main()
{
 char words[2][20] = { "Welcome to Xiyou","Linux Group 2022" };
 printf("%s\n", words[0]);
 printf("%s\n", words[1]);
 char* str = convertAndMerge(words);
 printf("str=%s\n", str);
 free(str);
 return 0;
}
char* convertAndMerge(char words[2][20])
{
 char* str = (char*)calloc(40, sizeof(char));//在函数中分配一段空间
 int n = 0;
 if (str != NULL)
 {
  for (int i = 0; i < 2; i++)
  {
   for (int j = 0; j < 20; j++)
   {
    if (words[i][j] != 0)
    {
     if (words[i][j] >= 'a' && words[i][j] <= 'z')
     {
      str[n] = toupper(words[i][j]);
     }
     else if (words[i][j] >= 'A' && words[i][j] <= 'Z')
     {
      str[n] = tolower(words[i][j]);
     }
     else {
      str[n] = words[i][j];
     }
     n++;
    }
   }
  }
 }
 return str;
}

10.
在这里插入图片描述
贴个图解释下吧!哎!
在这里插入图片描述

11.
在这里插入图片描述
1.argc是参数的个数,argv为指针数组的首元素
2.argc中总是存在一个参数,会自动传入一个命令。
3.不会。int在32位编译器中,int是32位,int最大值是231-1,第一位是符号位,用0表示正数,超出最大值就会产生进位将符号位变为1,变成负数,发生溢出
12.在这里插入图片描述
结果:Welcome to Xiyou Linux Group 2022
对于初始C语言的大家是不是感觉很神奇,这个居然会输出它。

本题主要考查大小端存储模式
大端模式:高位字节放在存在内存的低地址端,低位字节存放在内存的高地址端
地址由小到大增加,数据由高位向低位,与阅读习惯一致
小端模式:低位字节放在存在内存的低地址端,高位字节存放在内存的高地址端
将地址高低与数据位权有效结合,利于计算机处理

字符串复制函数strcpy()
strcpy(字符数组s1,字符串s2);
执行该函数时将字符串s2拷贝到字符数组s1中去
字符串连接函数strcat()
strcat(字符数组1,字符串2);
将字符串2连接到字符数组1中的字符串后面

接下来再分析一下:0x代表16进制,这时就可以看出是用ASCII码,每两位对应一个字符(这个我就不一一给大家画出来了,我给大家附一张表),四个字符一个逗号是int占4个字节,而字符占一个字节。
在这里插入图片描述
13.
在这里插入图片描述
结果:2 1 1
1 2 2
2 2
5 5 2

宏定义
宏定义是预处理命令的一种,在C语言源程序用一个标识符来表示一个字符串
使用宏定义可以方便程序的修改和提高程序的运行效率哦!
先简单介绍一下 不带参数的宏定义
#define 标识符 字符串
标识符称为宏名,在编译预处理时,用宏定义中的字符串去替换宏名,称为宏替换或宏展开。
字符串可以是常量、表达式、格式串
再来介绍一下 带参数的宏定义
#define 宏名(形参表) 字符串

那么说到预处理阶段,简单了解下一个C语言程序从代码到可执行程序的过程需要四个阶段:预处理,编译,汇编,链接
回到本题中 ①第一行的宏定义未加大括号,所以条件是否满足a=b;b=t语句都会执行,
②第二行的宏定义就要更加小心了,一定要注意使用带参数的宏时,如果宏的实参为表达式,则在定义带参宏时,字符串内的形参通常要用括号括起来以避免出错。例如

#define s(a,b) a*b
int a=1;
int b-2;
data=s(a+b,a+b);

你认为的会不会就是输出了9呢?那是人脑思维,计算机只会代!* - *
分析:data=1+2*1+2=5,所以如果你想输出9就一定要带上括号!!!

#define s(a,b) (a)*(b)

③不知道有没有伙伴会认为z和w的值是4呢?看下图,结果显而易见了吧^ - ^
在这里插入图片描述

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值