1.下面代码段将打印出多少个‘=’?运用相关知识解释该输出。
int main(int argc, char *argv[]) {
for (unsigned int i = 3; i >= 0; i--)
putchar('=');
}
无数个‘=’,
这是个简单的for循环,它的条件是i>=0,i初始值为3,循环迭代条件是i--,看似没问题,实际上,i的数据类型是unsigned int,没有负值,永远大于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的值转化成一个算数式子储存,以便交换。
第三种是通过异或的原理,a^b^a的值为b,a^b^b的值是a.
3.有如下代码段所示的函数 f,当我们执行该函数时,会产生什么样的输出结果?在同一程序中 多次执行该函数,输出结果是否一致?
void f() {
static int a = 0;
int b = 0;
printf("%d, %d\n", ++a, ++b);
}
++a是先加,再计算,a++是先计算在加。
对于多次执行该程序,结果不同,a的值一直变大,b一直是1.原理我上篇博客的第四题说过,就不再在此赘续了。
4.下面程序段的输出是什么?请解释该现象并说出与之相关尽可能多的知识。
int main(void) {
printf("%d\n", printf("Xiyou Linux Group2%d", printf("")));
}
结果:Xiyou Linux Group2019
这个是printf的返回值的原因,printf的返回值是它所包含的字符的个数。(再多想不到了)
5.执行下面的代码段,会输出什么?请试着解释其原因,并叙述相关知识。
int main(int argc, char *argv[]) {
char ch = 255;
int d = a + 1;
printf("%d %d", ch, d);
}
我觉得a好像少加了个‘’,应该是
int d = 'a' + 1;
输出结果:-1 98
这道题考的是ascii码,ascii一般是127位,255是拓展出来的。
对于255:以int来看,它的原码为1111 1111,再以char来看,char类型一个字节,正好占满 ,计算出补码是 1 000 0001 ,所以输出-1.
对于d:a的ascii码为97,“+1”后就是98.
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=1 , 1|0=1 , 0|0=0(直接上),所以++x与y++都要运算(记得补码),++x是先加再位运算,y++是位运算完后再加,所以第一次运算完后t为-1,
11111111 11111111 11111111 11111110
00000000 00000000 00000000 00000011
结果:11111111 11111111 11111111 11111111
转换成原码:10000000 00000000 00000000 00000001//-1
逻辑运算符||,作用:两个中至少有一个为真,就返回真,否则假。
++x结果为0,假,所以继续判断y++,y结果为4,为真,所以结果为真,返回1。,即t=1。
7.下面代码段的输出结果是什么?输出该结果的原因是?
#define X a+b
int main(int argc, char *argv[]) {
int a = 1, b = 1;
printf("%d\n", X*X);
}
结果为3,宏是简单的替换,即输出结果是printf(“%d\n”,1+1*1+1)。(写宏记得加括号)
8.请解释下面代码段中每一句的效果。
int val = 2018;
int *pi = 2019;
pi = &val;
*pi = 0;
第一句为给int类型变量val赋值,
第二句是给int类型指针变量pi赋值(这里是给int*类型赋值int类型,所以pi储存的的地址为2019,这是个危险的地方,因为,不知道2019指向哪里),
第三句是将val的地址赋给pi。
第四句是将pi所指向的地址的值修改为0,即将val修改为0
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
这里先对p分配了动态内存,然后将p储存的地址给了q,所以q,p指向一个地址,scanf先输入p的值,然后输入q的值,因为地址一样,所以q的值会更改p的值,所以p和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[0]的地址,a+1就是a的地址加a的类型的字节数,即a[1].
&a相当于二维数组的首地址,所以&a+1就是a[0]的地址+二维数组中的一个一维数组的字节数,比如这里就是(+4*4)。
11.斐波那契数列是这样的一串数列:1,1,2,3,5,8,13,......。在这串数列中,第一项、第二项 为 1,其他项为前两项之和,该数列的第 x 项可以表示为下面的函数。请根据描述,写出一个程 序,使之输入 x 后,能够输出斐波那契数列的第 x 项(其中 x<30)。当你完成之后,你可以尝试 使用递归解决这个问题。
(怎么去水印啊)
int fb(int num){
if(num==1||num==2){
return 1;
}
if(num>2){
return fb(num-1)+fb(num-2);
}
}
int main(){
int num=0;
scanf("%d",&num);
num=fb(num);
printf("%d",num);
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;
}
}
}
}
这是冒泡排序的算法。
冒泡排序,就是像冒泡一样,最小的数会慢慢到最后面或最前面。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
排序算法:冒泡排序,选择排序,插入排序(还有希尔排序,堆排序,快速排序,并归排序,桶排序等,这些就不说了,不然感觉这篇博客能上万字(其实是我懒))
选择排序:就是在数组中选择最大或最小的数,放到最前面或最后面,再选择第二大或第二小的,依次排序。
int main(int argc, char *argv[]) {
int nums[6] = { 6, 3, 2, 4, 5, 1 };
for(int i=0;i<6-1;i++){
int max=i;
for(int j=i+1;j<6;j++){
if(nums[j]>nums[max]){
max=j;
}
}
if(max!=i){
nums[max]^=nums[i];
nums[i]^=nums[max];
nums[max]^=nums[i];
}
}
}
插入排序:构造一个有序数列,将后面的数字逐个插入。
int main(){
int nums[6] = { 6, 3, 2, 4, 5, 1 };
for(int i=1;i<6;i++){
for(int j=i-1;j>=0&&nums[j]<nums[j+1];j--){
nums[j]^=nums[j+1];
nums[j+1]^=nums[j];
nums[j]^=nums[j+1];
}
}
}
13.请简单叙述两种字节序(大端、小端)的概念,你的机器是什么字节序?试着写一个 C 语言程 序来验证,如果你没有思路,你可以尝试着使用联合体或者指针。
大端:低地址存储高字节,高地址存储低字节。
小端:高地址存储高地址,低地址存储低字节。
小端有利于类型的强制转换,比int->char,直接截取低地址处的。
详解可以看:大小端详解_HanSion.Z-CSDN博客_大小端
测试:
int main(){
int num = 0x12345678;
char cs = *(char*)#
if ( cs == 0x12 )
printf("大端");
else{
printf("小端");
}
}
上篇博客写过的,直接搬过来了。