1.下面代码打印出多少个‘=’?
int main(int argc,char*argv[ ]) {
for(unsigned int i = 3; i >=0;i--)
putchar(' = ');
}
解答:无数个0
因为i的类型是unsigned int永远为非负值,所以该循环将不会终止。
2.下列三种交换整数的方式是如何实现交换的?
/* (1) */ int c = a; a = b ; b = c;
/* (2) */ a = a - b; b = b + a; a = b - a;
/* (3) */ a ^= b ; b ^= a ; a ^= b;
解答:1)通过变量间的赋值
2)通过变量与表达式间的赋值
3)通过“^"(异或)运算
比如 a 为 5 --- 0101
b 为 7 ----0111
则a^b=0010———两个二进制数对应位相同为0,不同为1.可推得a^b^a=a
3.我们执行如下函数f时,会产生什么样的输出结果?在同一程序中多次执行该函数,输出结果是否一致?
void f() {
static int a = 0;
int b = 0;
printf("%d, %d\n", ++a, ++b);
}
解答:执行第一次,会输出1, 1.
在第二次,输出2, 1.
这是因为在函数块内定义的变量,是局部变量,通常被默认为自动储存类型。意思是它只在这个函数中存在,当函数执行完成它将被销毁,因此每次引用函数它都将被重新定义初始化,就像b.但a就不一样,它被static修饰,是局部静态变量,函数完成后不被销毁,可在多个函数块间引用,因此将持续加1.
4.下面程序段的输出是什么?请解释该现象并说出与之相关尽可能多的知识。
int main(void) {
printf("%d\n", printf("Xiyou Linux Group2%d", printf("")));
}
解答:Xiyou Linux Group2019
因为printf的返回值是有效字符串个数(不包括\0)
最内部的printf优先级最高
5.执行下面代码段会输出什么?
int main(int argc, char *argv[]) {
char ch = 255;
int d = a + 1;
printf("%d %d", ch, d);
}
解答:a的ascii码是97,所以b以整数输出值为98. 255用二进制表示为11111111,在计算机中以补码形式储存为10000001因此%d输出-1.
在计算机系统中,数值一律用补码来存储,主要原因是:
- 统一了零的编码
- 将符号位和其它位统一处理
- 将减法运算转变为加法运算
- 两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃
6.执行以下的代码,将进行什么样的输出?手动计算代码中t的值。
int main(int argc, char *argv[]) {
char x = -2, y = 3;
char t = (++x) | (y++);
printf("x = %d, y = %d, t = %d\n", x, y, t);
t = (++x) || (y++);
printf("x = %d, y = %d, t = %d\n", x, y, t);
}
解答:x = -1, y = 4, t = -1
x = 0, y = 5, t = 1
符号 描述 运算规则
& 与 两个位都为1时,结果才为1
| 或 两个位都为0时,结果才为0
^ 异或 两个位相同为0,相异为1
~ 取反 0变1,1变0
<< 左移 各二进位全部左移若干位,高位丢弃,低位补0
>> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的
补符号位(算术右移),有的补0(逻辑右移)
7.下面代码输出结果是什么?该输出结果的原因是?
#define X a+b
int main(int argc, char *argv[]) {
int a = 1, b = 1;
printf("%d\n", X*X);
}
解答:3
宏定义是单纯的替换,不会做求值等其他运算。所以相当于1+1*1+1=3.
8.解释下列代码每一句的效果。
int val = 2018;
int *pi = 2019;
pi = &val;
*pi = 0;
解答:1)开辟2字节的空间储存val变量,并赋给它2018的值。
2)把2019储存在pi指向的位置,但是pi未初始化,其值是一个随机值,这一举动可能会擦除代码或导致程序崩溃。
3)初始化pi使pi指向val
4)将0存进pi所指,相当于将0赋值给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 %s\n", p, q);
}
解答:linux linux
第二行代码相当于创建了可以容纳20个char类型的块,指针p指向这个块的首元素,正如同数组一样。那么第三行操作,使q同样指向第一个元素,所以两者可以看做相同的数组,输出值相同。
10.斐波那契数列1,1,2,3,5,8,13....首两项为1,后一项是前两项之和,写一个函数,使输入x后能输出第x项。完成之后尝试用递归解决这个问题。
解答:逻辑推导
#include <stdio.h>
int main()
{
int x;
scanf("%d",&x);
int a=1,b=1,c;
if (x<=2)
printf("1");
else
for(int i=0;i<x-2;i++)
{
c=a+b;
a=b;
b=c;
}
printf("%d",c);
}
递归
#include <stdio.h>
int f(int a){
if(a==1||a==2){
return 1;
}
if(a>2){
return f(a-1)+f(a-2);
}
}
int main(){
int a=0;
scanf("%d",&a);
a=f(a);
printf("%d",a);
return 0;
}
12.你知道下面的是什么排序吗?试着讲解其原理,并尝试改进它。你还知道其他的排序吗?
int main(int argc, char *argv[]) {
int nums[6] = { 6, 3, 2, 4, 5, 1 };
for (int i = 0; i < 6; i++) {
for (int j = i; j < 6; j++) {
if (nums[i] > nums[j]) {
int c = nums[i];
nums[i] = nums[j];
nums[j] = c;
}
}
}
解答:是冒泡排序。
使用了嵌套循环,定住一个地址,让处于该地址的元素与其后(不是全部)所有元素比较,并将其中最小的元素置于此处,直至遍历数组。从而由小到大排列数组元素。
直接插入排序
基本思想
将待排序的无序数列看成是一个仅含有一个元素的有序数列和一个无序数列,将无序数列中的元素逐次插入到有序数列中,从而获得最终的有序数列。
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置中
- 重复步骤2
13.请简单叙述两种字节序(大端,小端)的概念。你的机器是什么字节序?试着写一个c语言程序来验证,如果你没有思路,你可以尝试着使用联合体或指针。
解答:
大端 是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。
小端 是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。
理解:
验证:
#include <stdio.h>
int main()
{
int a=1; //a在计算机中储存为00 00 00 01
char* p = (char*)&a;//使P指向a的地址的数组,也就是说p指向&a的第一位
printf("%d",*p);//取出该位置的值,如果为0为大端,1则小端
}