2020——xiyouLinux面试题

本文通过一系列C语言代码示例,详细解析了变量类型、位操作、函数调用、数组、指针、内存管理以及递归等核心概念,深入探讨了程序运行时的内存布局和数据处理机制。同时,强调了指针返回局部变量地址的潜在问题以及动态内存分配的注意事项。此外,还涉及到了字符串处理、位移运算在ASCII码中的应用以及数组地址和指针的关系。
摘要由CSDN通过智能技术生成

1.

请试着解释其输出。

int main(int argc , char *argv[])
 {
		 unsigned char a = 255;
		 char ch = 128;
		 a -= ch;
		 printf("a = %d ch = %d\n", a, ch);
}
---------------------------------------------
a = 127 ch = -128

涉及到取值范围的问题,char类型的取值范围为-128~127
255是一个整数,在计算机中存储数据采用补码的形式,而正数原码补码相同,即

原码  1111 1111
反码  1111 1111
补码  1111 1111

有符号数正数最高位是0,所能取到的最大值为127,而128超过了这个范围。

2.

下面代码的运行输出结果是什么,并说说你的理解。

int main(int argc, char *argv[])
 {
	 char *str = "Xi You Linux Group 20";
	 printf("%d\n", printf(str));
	 return 0; 
 }
 ---------------------------------------------------
 Xi You Linux Group 2021

解析:
本题考察printf()函数的返回值,查看man手册我们可以知道:Upon successful return, printf() return the number of characters printed.(成功返回后,printf() 返回打印的字符数。)

即printf()函数返回打印的字符数。"Xi You Linux Group 20"有21个字符(包括空格),则先打印str,后打印返回值21
6

3.

这段代码的输出结果是什么?为什么会出现这样的结果?

int i = 2;
void func() 
{
		 if(i != 0) 
		 {
				 static int m = 0;
				 int n = 0;
				 n++;
				 m++;
				 printf("m = %d, n = %d\n", m, n);
				 i--;
				 func();
		 } 
		 else 
		 {
		 		 return;
		 } 
 }
int main(int argc, char *argv[]) 
{
		 func();
		 return 0; 
 }
 -------------------------------------------------------
 m = 1, n = 1
m = 2, n = 1

解析:
本题重点在于两个变量:m、n
其中:m是具有静态存储期的块作用域变量,n是具有自动存储期的块作用域变量
所谓具有静态存储期,其实就是指该变量储存在静态内存中,它从程序被载入到程序结束期间都存在。

4.

下面程序会出现什么结果?为什么会出现这样的结果?

int main(int argc, char * argv[]) 
{
	 char ch = 'A';
	 int i = 65;
	 unsigned int f = 33554433;
	 *(int *)&f >>= 24;
	 *(int *)&f = *(int *)&f + '?';
	 printf("ch = %c i = %c f = %c\n", ch, i, *(int *)&f);
	 return 0;
} 
-----------------------------------------------------
ch = A i = A f = A

解析:
本题考察移位运算符 >>/<<与ascii码的理解,重难点在变量f

*(int *)&f,考察取地址、强制类型转换以及解引用的知识。

在进行位移运算之前,先将f转化为二进制,然后再按位右移:

10000000000000000000000001 ==> 00000000000000000000000010 (2)

'?'的ascii码为63,63(?) + 2 = 65(A)

5.

下面代码的运行输出结果是什么,并说说你的理解。

int main(int argc, char *argv[]) 
{
	 int a[2][2];
	 printf("&a = %p\t&a[0] = %p\t&a[0][0] = %p\n", &a,&a[0],&a[0][0]);
	 printf("&a+1 = %p\t&a[0]+1 = %p\t&a[0][0]+1= %p\n",&a+1,&a[0]+1, &a[0][0]+1);
	 return 0; 
 }
 -----------------------------------------------------
 &a = 0x7fff604b9900     &a[0] = 0x7fff604b9900  	&a[0][0] = 0x7fff604b9900
&a+1 = 0x7fff604b9910   &a[0]+1 = 0x7fff604b9908    &a[0][0]+1 = 0x7fff604b9904

数组名
注意,输出的结果为16进制,因此9900在加16字节之后变为9910。

6.

下列程序的功能是什么?有什么问题,你能找出问题并解决它吗?

int* get_array() 
{
	 int array[1121]; 
	 for (int i = 0; i < sizeof(array) / sizeof(int); i++) 
	 {
	 		array[i] = i;
	}
	 return array;
}
int main(int argc, char *argv[])
 { 
 		int *p = get_array();
}
--------------------------------------------------
作用:
给数组赋值,大小为数据下标的大小。
即array[0] = 0, array[1] = 1, array[100] = 100
---------------------------------------------------
问题
函数get_array()返回的array是一个局部变量的地址
在函数get_array()结束之后,该地址内存上的数据被清除
即返回的是一个垃圾地址

7.

下面代码的运行输出结果是什么,并说说你的理解。

int main(int argc, char *argv[]) {
	 char str[] = "XiyouLinuxGroup"; 
	 char *p = str; 
	 char x[] = "XiyouLinuxGroup\t\106F\bamily";
	 printf("%zu %zu %zu %zu\n", sizeof(str), sizeof(p),
	sizeof(x), strlen(x));
	 return 0; 
}
-----------------------------------------------------
16 8 25 24

本题考察对转义字符的理解

其中%zu输出size_t即unsigned int;
字符数组x中:\t表示移到下一个水平制表位,\b将当前位置移到前一列,\106表示’F’,106在ascii码中表示八进制的’F’。

8.

如下程序,根据打印结果,你有什么思考?

int add(int *x, int y) {
	 return *x = (*x^y) + ((*x&y)<<1);
}
int a;
int main(int argc, char *argv[]) {
	 int b = 2020;
	 if(add(&b, 1) || add(&a, 1)) {
		 printf("XiyouLinuxGroup%d\n", b);
		 printf("Waiting for y%du!\n", a);
	 }
	 if(add(&b, 1) && a++) {
		 printf("XiyouLinuxGroup%d\n", b);
		 printf("Waiting for y%du!\n", a);
	}
	 return 0;
} 
------------------------------------------------
XiyouLinuxGroup2021
Waiting for y0u!

9.

在下段程序中,我们可以通过第一步打印出 a 的地址,假如在你的机器上面打印结果是 0x7ffd737c6db4;我们在第二步用 scanf 函数将这个地址值输入变量 c 中;第三步,随机输入一个数字,请问最终输出了什么结果,你知道其中的原理吗?

void func() 
{ 
	 int a = 2020;
	 unsigned long c;
	 printf("%p\n", &a);
	 printf("我们想要修改的地址:");
	 scanf("%lx", &c);
	 printf("请随便输入一个数字:");
	 scanf("%d", (int *)c);
	 printf("a = %d\n", a);
}
---------------------------------------------
第二个sacnf()输入的值

scanf()
scanf()是将读取到的数据存入一个内存地址中
第一个scanf()将变量a的地址赋值给变量c,这时变量c的内存存储的值为变量a的内存地址;
我们注意到:第二个scanf()没有取地址符’&’,因此,scanf()将输入的值赋值给地址&a

10.

请问一个 C 语言程序从源代码到可执行文件中间会进行哪些过程,你能简单描述一下
每个环节都做了什么事情吗?
点此

因前几次面试题已有类似的题目,在此省略

11.

请解释一下这行代码做了什么?

puts((char*)(int const[]){
0X6F796958,0X6E694C75,0X72477875,
0X3270756F,0X313230,0X00000A
});

大小端问题,同上忽略

12.

请随机输入一串字符串,你能解释一下输出结果吗?

int main(int argc, char *argv[]) 
{
	 char str[1121];
	 int key;
	 char t;
	 fgets(str, 1121, stdin);
	 for(int i = 0; i < strlen(str) - 1; i++) 
	 {
		 key = i;
		 for(int j = i + 1; j < strlen(str); j++) 
		 {
			 if(str[key] > str[j]) 
			 {
			 		key = j;
			 }
		 } 
		 t = str[key];
		 str[key] = str[i];
		 str[i] = t;
	 } 
	 puts(str);
	 return 0; 
} 
--------------------------------------------------
输入:edcba
输出:abcde

13.

用循环和递归求 Fibonacci 数列,你觉得这两种方式那种更好?说说你的看法。如果让你求 Fibonacci 数列的第 100 项,你觉得还可以用常规的方法求解吗?请试着求
出前 100 项的值(tip 大数运算)。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值