1.下面代码段将打印出多少个‘=’?运用相关知识解释该输出。
int main(int argc, char *argv[]) {
for (unsigned int i = 3; i >= 0; i--)
putchar('=');
}
c语言存在隐式转换,由于i的类型是unsigned int ,所以
i恒>=0,程序一直执行。
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;
第一个直接记录原始数据。
第二种记录两者之间的差,a - b 就是差,不妨记做c, 所以a(原来的) = c + b, 现在要交换a, b, 那么b(a) = b + a©, 就把b换成了a, 然后b(原来的) = a(原来的) - c(差), 现在就是的b(原来的) = b(a) - a。
第三种 不理解异或的集合解释
搬了张图片,从集合的角度理解
3.有如下代码段所示的函数 f,当我们执行该函数时,会产生什么样的输出结果?在同一程序中 多次执行该函数,输出结果是否一致?
void f() {
static int a = 0;
int b = 0;
printf("%d, %d\n", ++a, ++b);
}
static修饰局部变量的时候作用域是函数, 生存期是静态, 所以会多次加。
4.下面程序段的输出是什么?请解释该现象并说出与之相关尽可能多的知识。
printf("%d\n", printf("Xiyou Linux Group2%d", printf("")));
函数参数的压栈顺序是从左往右,随边找个函数printf一下地址就可以证明, 然后就由内往外拆解, 第一个printf返回0,然后第二个返回19
5.执行下面的代码段,会输出什么?请试着解释其原因,并叙述相关知识。
int main(int argc, char *argv[]) {
char ch = 255;
int d = ch + 1;
printf("%d %d", ch, d);
}
char ch = 255, ch就是(111…11)B, 第二句右边的结果是上溢后8位的0, 然后被提升成了32位0, 输出结果中%d是以十进制解读数据,要按补码来。
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);
}
t = -1 | 3; -1补码为全1, 所以结果为全1, t = -1;
接着是逻辑或,0 || 4, 结果为真,t = 1;
7.下面代码段的输出结果是什么?输出该结果的原因是?
#define X a+b
int main(int argc, char *argv[]) {
int a = 1, b = 1;
printf("%d\n", X*X);
}
预处理的替换是直接替换, 所以有优先级的问题。
8.请解释下面代码段中每一句的效果。
int val = 2018;
int *pi = 2019;
pi = &val;
*pi = 0;
不太懂 int *pi = 2019, 编译的过不了, 给地址赋2019…
第一句定义变量val对象的值为2018;
23句取得val的地址给pi, 4通过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 %s\n", p, q);
}
p, q指向同一对象, q后修改, 所以会输出两次q;
10.执行下面的程序段,每次执行的输出结果一致吗,整理并解释输出结果。
int main(int argc, char *argv[]) {
int a[4] = { 2, 0, 1, 9 };
printf("%p, %p\n", a, &a);
printf("%p, %p\n", a + 1, &a + 1);
}
a 和 &a的数据类型不同, 目的是为了做指针偏移的步长不同,但是地址是一样的,如果把数组名理解成指针(现在越来越觉得没必要这么搞)的话, 就是指向其第一个元素的指针, a[0]是int,所以 a + 1的地址就是 &a[1], &a是指向一个有四个int的数组 int [4], 所以 &a + 1的地址就是a[4]
11.斐波那契数列是这样的一串数列:1,1,2,3,5,8,13,…。在这串数列中,第一项、第二项 为 1,其他项为前两项之和,该数列的第 x 项可以表示为下面的函数。请根据描述,写出一个程 序,使之输入 x 后,能够输出斐波那契数列的第 x 项(其中 x<30)。当你完成之后,你可以尝试 使用递归解决这个问题。
记忆化搜索, 没什么好说的。
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;
}
}
}
}
zhuming的新手福音写发, 不考虑一切的情况下两眼一闭。
改进,记下最后一次发生交换的位置
void f(int *a, int n)
{
for (int last = n, j; last != 0; last = j) {
for (j = 0; j < last - 1; j++) {
if(a[j] > a[j + 1]) swap(a[j], a[j + 1]);
}
}
}
13.请简单叙述两种字节序(大端、小端)的概念,你的机器是什么字节序?试着写一个 C 语言程 序来验证,如果你没有思路,你可以尝试着使用联合体或者指针。
就是内存是分字节的, 所以数据写入就有一个顺序的问题。
int main(int argc, char *argv[]) {
int a = 0x12345678;
printf("%x\n", *(char *)&a);
printf("%x\n", *((char *)&a + 1));
printf("%x\n", *((char *)&a + 2));
printf("%x\n", *((char *)&a + 3));
}
可以看出来对象的起始地址是低地址, 然后是数据的低字节部分, 属于小端, 低尾端。
14.以下是在某机器下执行 Linux 命令 ls 的部分输出(有删节),参考该输出,你可以说出哪些关 于该命令以及其他 Linux 的相关知识?
[[root@xiyoulinux /]# ls -al
total 36
drwxr-xr-x 17 root root 4096 Sep 21 23:45 .
drwxr-xr-x 17 root root 4096 Sep 21 23:45 ..
lrwxrwxrwx 1 root root 7 Aug 21 22:21 bin -> usr/bin
drwxr-xr-x 4 root root 2048 Jan 1 1970 boot
drwxr-xr-x 21 root root
drwxr-xr-x 83 root root
drwxr-xr-x 4 root root
drwxr-xr-x 2 root root
drwxr-x--- 9 root root
dr-xr-xr-x 13 root root
drwxrwxrwt 10 root root
drwxr-xr-x9 root root 3580 Nov 21 21:16 dev
略过吧