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] 的指针)在指针的类型上是有区别的。
代码如下:
#includeint 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; }
原理不再赘述。
冒泡排序,改进如下:
#includeint 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; }
#includeint 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命令



