栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

西邮Linux兴趣小组2019纳新面试题简析

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

西邮Linux兴趣小组2019纳新面试题简析

1.下面代码段将打印出多少个‘=’?运用相关知识解释该输出。
int main(int argc, char *argv[]) {
for (unsigned int i = 3; i >= 0; i--)
putchar('=');
}

会打印无数个‘=’

由于i是 unsigned int ,所以i不会小于0,当i=0时,执行i-1之后,i会变为429496795(不同编译器可能结果不同),原因不再赘述,读者自行查阅。

2.下列三种交换整数的方式是如何实现交换的?
 int c = a; a = b    ; b = c;
 a = a - b; b = b + a; a = b - a;
 a ^= b    ; b ^= a    ; a ^= b;

(1)引入第三个变量

(2)算数运算

(3)异或运算

原理请自行查阅。

3.有如下代码段所示的函数f,当我们执行该函数时,会产生什么样的输出结果?在同一程序中多次执行该函数,输出结果是否一致?
void f() {
    static int a =0;
    int b = 0;
    printf("%d, %dn",++a, ++b);
}

输出1,1

多次调用该函数会输出并不一致,会依次输出以下内容:

1,1

2,1

3,1

......

(以此类推)

原因是static int a是一个静态局部变量,只灰进行一次初始化。静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变,即仍为函数结束时的值,下一次调用函数时它的值为上一次函数结束时的值。其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束。而b则是普通变量,每次都被重置,初始化为0。

关于静态变量,读者可自行搜索,不再赘述。

4.下面程序段的输出是什么?请解释该现象并说出与之相关尽可能多的知识。
int main(void) {
    printf("%dn", printf("Xiyou Linux Group2%d", printf("")));

输出内容为:Xiyou Linux Group2019       下面进行分析:

从后往前分析,printf("")    什么都不打印,返回值为0,返回值0作为    printf("Xiyou Linux Group2%d"   中%d的输出内容,即%d替换为0。并且将    Xiyou Linux Group20    打印在屏幕上。这个printf打印了19个字符,其返回值为19,返回值十九作为     printf("%dn"     中的%d的输出内容,即打印19在屏幕上。连起来即为  Xiyou Linux Group2019

相关知识可以了解以下printf函数及其返回值。自行查阅。

5.执行下面的代码段,会输出什么?请试着解释其原因,并叙述相关知识。
int main(int argc, char *argv[]) {
char ch = 255;
int d = ch + 1;
printf("%d %d", ch, d);
}

输出为:-1 0 

char只有一个字节,八个二进制位,只能表示-128——127,共256个数,00000000~011111111表示0~127,10000000~11111111表示-128~-1,这里是有关于数字在就算及内部的存储运算方式——二进制补码有关,读者可自行查阅。总之将255赋给char,结果char里存储的是-1,+1之后是0,所以输出为:-1 0.

6.执行以下代码段,将产生什么的输出?请对输出加以解释,并手动计算代码中t的值。
int main(int argc, char *argv[]) {
 char x =-2, y =3;
 char t =(++x) |(y++); 

 printf("x = %d, y = %d, t = %dn", x, y, t);
 t =(++x) ||(y++);
 printf("x = %d, y = %d, t = %dn", x, y, t);
}

输出为:

x = -1, y = 4, t = -1
x = 0, y = 5, t = 1

         char t = (++x)| ( y++ );:x加一后的值与y加一前的值进行按位或运算,即-1的二进制补码11111111和3的二进制补码00000011进行按位或运算,结果为11111111,即t = -1.

输出x = -1, y = 4, t = -1

       t =(++x) || (y++);:0和4进行或运算,结果为真,即1,打印x和y递增后的值和t

输出x = 0, y = 5, t = 1

7.下面代码段的输出结果是什么?输出该结果的原因是?
#define X a+b

int main(int argc, char*argv[]) {
 inta =1, b =1;
 printf("%dn", X*X);
}

结果为 3

             define为纯文本替换,X*X替换为a+b*a+b,由于*优先级高,所以结果为1+1+1=3,打印3

8.请解释下面代码段中每一句的效果。
int val =2018;
int*pi =2019;
pi =&val;
*pi =0;

依次为:

定义整形变量int val 并初始化为2018

pi为一个指向int类型变量的指针,该变量地址(pi的值)为0x7e3(2019)

让pi指向val(pi的值变为val的地址)

将0赋给pi所指的变量(即val)

9.执行下列程序段,并输入“Xiyou Linux”(不含引号),那么程序的输出结果是什么?请解释其原因。
 int main(int argc, char*argv[]) {
    char *p = (char*)malloc(sizeof(char) *20),
    *q = p;
    scanf("%s %s", p, q); 
    printf("%s %sn", p, q);
}

输出结果为:Linux Linux

char *p = (char*)malloc(sizeof(char) *20),*p = p为让*p指向了一个可以容纳20个char的空间,q初始化为一个指向p所指的地方的指针,即p和q指向同一个地方。

scanf("%s %s", p, q);scanf先读取第一个字符串Xiyou放在p所指的地方,接着读取第二个字符串Linux放在q所指的地方。因为p和q指向同一个地方,所以第二次读取的字符串覆盖了第一次读取的字符串,即这个地方最终保存的只有Linux,之后打印两次都是这个地方的值Linux

10.执行下面的程序段,每次执行的输出结果一致吗,整理并解释输出结果。
int main(int argc, char*argv[]) {
    int a[4] ={ 2, 0, 1, 9};
    printf("%p, %pn", a, &a);
    printf("%p, %pn", a +1, &a +1);
 
}

输出结果为(本机):

0x7fffffffe260, 0x7fffffffe260
0x7fffffffe264, 0x7fffffffe270

(1)数组名a实际指的是数组的第一个元素的地址。

(2)&a指的是数组的首地址,即数组第一个元素的地址。

(3)a+1是数组首地址加上一个元素所占的地址大小,这里int是4个字节,所以加上1x4.

(4)&a+1代表的是加上整个数组的大小,这里数组尺寸是4,所以+1代表的是地址加上4x4.

       读者可查阅《c和指针》p141和p142页以及其他页的内容进行相关知识的学习,简单说一下:

       在C中, 在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址。 它的类型取决于数组元素的类型: 如果它们是int类型,那么数组名的类型就是“指向 int 的常量指针“。

        在以下两种场合下,数组名并不是用指针常量来表示,就是当数组名作为 sizeof 操作符 和 单目操作符 & 的操作数时。sizeof 返回整个数组的长度,而不是指向数组的指针的长度。 取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量的指针。所以 &a 后返回的指针便是指向数组的指针,跟 a(一个指向 a[0] 的指针)在指针的类型上是有区别的。
 

 代码如下:

#include
int fbnq(int n)
{
	if (n <= 2)
		return 1;//n=1,2   返还1;
	else
		return fbnq(n - 1) + fbnq(n - 2);//n>2   返还前两个数之和
}
int main()
{ 
	int n = 0;
	scanf_s("%d", &n);
	int ret = fbnq(n);
	printf("%dn", ret);
	return 0;
}

原理不再赘述。

 

 冒泡排序,改进如下:

#include 
int main(int argc,char *argcv[])
{
	int nums[6] = { 6, 3, 2, 4, 5, 1 };
	int t;
	for (int i = 0; i < 5; i++){    
		for (int j = 0; j < 6 - i; j++){
            if (nums[j] > nums[j + 1]){      
				t = nums[j];
				nums[j] = nums[j + 1];      
				nums[j + 1] = t;
			}
		}
	}
}

基本原理:

每次比较相邻的两个元素。如果第一个比第二个大(假设从小到大排序),就交换他们两个(否则不交换)。

第一次比较第1,2个的元素的大小(并交换),接着比较第2,3个元素的大小(并交换)......第一趟可以将最大的数放到最后一个位置,第二趟可以将第二大的数放到倒数第二个位置,每一趟比较的次数依次减少,以此类推,直到排序完成。

此图可以生动形象的展示其原理:

其他排序方法还有:选择排序,插入排序,希尔排序,快速排序,归并排序,堆排序等,转载一个介绍这些算法的链接链接:
常见的7种排序算法_ispurs的博客-CSDN博客_排序算法

常见的7种排序算法_ispurs的博客-CSDN博客_排序算法

首先明白几个概念:

(1)字节序:

顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序。

(2)高/低地址端和高/低字节:

a.最低内存地址为0x00000000,最高内存地址为0xffffffff,即内存地址大的为高地址端。

b.高低字节是指数据,一串数据,左边为高位,右边为低位,比如0x12345678,它是一个32位十六进无符号整形,占据四个字节,从高到低依次为0x12、0x34、0x56和0x78。

接下来说大小端字节序:

大端(Big-Endian):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

小端(Little-Endian):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

仍然以0x12345678为例(具体地址为假设):

1.以大端字节序(Big-Endian)存储: 低地址存放高位:
栈底 (高地址端)
---------------
(0x78) -- 0xabcdef23
(0x56) -- 0xabcdef22
(0x34) -- 0xabcdef21
(0x12) -- 0xabcdef20
---------------
栈顶 (低地址端)

2.以小端字节序(Little-Endian): 低地址存放低位:
栈底 (高地址)
---------------
 (0x12) -- 0xabcdef23
 (0x34) -- 0xabcdef22
 (0x56) -- 0xabcdef21
 (0x78) -- 0xabcdef20
--------------
栈顶 (低地址端)

利用指针判断:

#include 
#include 
int main()
{
    int a=0x1234;
	char b=*(char*)&a;
	if(b==0x12)
		printf("big endn");
	else
		printf("little endn");
	return 0;
}
#include 
int main()
{
  union w
{
  int a;  //4 字节
  char b; //1 字节
} c;
  c.a=1;
  if (c.b==1)
  printf("It is Little_endian!/n");
  else
  printf("It is Big_endian!/n");
  return 1;
}

说明:

1.在C语言中,共用体(联合体)中的几种不同类型的变量存放在同一段内存单元中。
2.  联合体(共用体)的数据成员都是从低地址开始存放。

(以下地址为假设)
(1)  若是小端模式,由低地址到高地址c.a存放为0x01 00 00 00,c.b被赋值为0x01;
 
 地址: 0xabcdef20 0xabcdef21 0xabcdef22 0xabcdef23
   c.a     01                 00                 00                 00
   c.b     01                 00       
 
(2)若是大端模式,由低地址到高地址c.a存放为0x00 00 00 01,c.b被赋值为0x0;


   地址: 0xabcdef20 0xabcdef21 0xabcdef22 0xabcdef23
   c.a       00                 00                 00                 01
   c.b       00                 00    

(手机查看可能对不上。。。)          

由此,根据c.b的值是否为1即可判断是大端还是小端

 此题不多做展开,关于ls命令,转载他人链接:

Linux ls命令_micjlxx的博客-CSDN博客_ls命令


 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/612944.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号