1.
解释下面 C 语言代码段中每一句的语义。
int main(int argc, char *argv[])
{
int val = 2018; // 将 2018 赋值给 int 型变量 val
int *pi = 2019; // pi指向2019这个地址
pi = &val; // 将 val 的地址赋给指针pi
*pi = 0; // pi指向 0 这个地址
return 0; //
}
2.
下面的代码段将打印出多少个“=”?运用相关知识解释该输出。
int main(int argc, char *argv[])
{
for (unsigned int i = 3; i >= 0; i--)
{
putchar('=');
}
return 0;
}
会无限输出。
原因:
unsigned int 取值范围为0~4294967295,当i减到0后,再进行一次自减,会变为4294967295,永远满足>=0的条件,因此会打印出无数个’=’.
3
下面是三种交换整数的方式,它们是怎样实现交换的?
/* (1) */ int c = a; a = b ; b = c ; // 使用中间变量
/* (2) */ a = a - b; b = b + a; a = b - a; // 运用数学运算
/* (3) */ a = a ^ b; b = b ^ a; a = a ^ b; // 按位或
第三种交换方式步骤如下:
步骤 | a | b |
---|---|---|
初始 | a | b |
第一步 | a^b | b |
第二步 | a^b | b^( b ^a) = a |
第三步 | (a^ b ) ^ a = b | a |
4
有如下代码段所示的函数𝑓,当我们执行该函数时,会产生什么样的输出结果?在同一程序中多次执行该函数,输出结果是否一致?
void f()
{
static int a = 0;
int b = 0;
printf("%d, %d\n", ++a, ++b);
return 0;
}
调用四次函数,输出结果如下:
1, 1
2, 1
3, 1
4, 1
知识点:
static
点此学习
5
下面程序段的输出是什么?请解释该现象并说出与之相关尽可能多的知识。
int main(int argc, char *argv[])
{
printf("%d\n", printf("Xiyou Linux Group2%d", printf("")));
return 0;
}
结果
Xiyou Linux Group2019
知识点:printf()
printf()的返回值是打印出的符号的个数;
printf("%d\n",printf(“Xiyou Linux Group2%d”,printf("")));
第一步:第三个printf什么也没有打印,即返回值为0;
第二步:第二个printf打印Xiyou Linux Group20,长度为19,即返回值为19;
第三步:第一个printf打印出第二个printf的返回值19;
6
执行下面的代码段,会输出什么?请试着解释其原因,并叙述相关知识。
int main(int argc, char *argv[])
{
char ch = 255;
int d = ch + 1;
printf("%d %d", ch, d);
return 0;
}
char类型的取值范围为-128~127
255是一个整数,在计算机中存储数据采用补码的形式,而正数原码补码相同,即
原码 1111 1111
反码 1111 1111
补码 1111 1111
此时用char来看待这个二进制数字,由于符号位为1,则为负数,负数由补码求原码
补码 1111 1111
原码 1000 0001
结果为-1
总结:1111 1111用int来看是255,用char来看是-1.
7
执行以下代码段,将产生什么样的输出?请对输出加以解释,并手动计算代码中 t 的值。
int main(int argc, char *argv[])
{
char x = -2, y = 3;
char t = (++x) | (y++);
//++x = -1 (1 1 1 1 1 1 1 1) y++ = 3 (0 0 0 0 0 0 1 1)
// 1 1 1 1 1 1 1 1
// | 0 0 0 0 0 0 1 1
//----------------------
// 1 1 1 1 1 1 1 1 ( t = -1 )
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);
return 0;
}
结果
x = -1, y = 4 , t = -1
x = 0, y = 5 , t = 1
知识点
前缀:先给变量加减1,再取出来做表达式的值
后缀:先把变量的值拿出来作表达式的值,再给变量加减1
则输出
x=-1,y=4,t=-1
x=0,y=5,t=1
8
8.下面代码段的输出结果是什么?输出该结果的原因是?
#define X a + b
int main(int argc, char *argv[])
{
int a = 1, b = 1;
printf("%d\n", X * X);
return 0;
}
宏:简单的替换,但需要注意的是在宏定义中表达式两边的括号不能少,否则在宏展开以后可能会产生歧义.
题目中表达式为 1+1*1+1 输出3
9
9.执行下列程序段,并输入“Xiyou Linux”(不含引号),那么程序的输出
结果是什么?请解释其原因。该程序中有一处隐患,请找出并说明。
int main(int argc, char *argv[])
{
char *p = (char *)malloc(sizeof(char) * 20);
char *q = p;
scanf("%s %s", p, q);
printf("%s %s\n", p, q);
return 0;
}
输出 Linux Linux
第二行代码为20个char类型的值请求内存空间,并设置p指向该位置.
p和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);
return 0;
}
0x7ffee5db1110 0x7ffee5db1110
0x7ffee5db1114 0x7ffee5db1120
a表示数组的首地址,&a表示数组首元素的地址
a+1表示数组首地址加上一个元素所占的地址大小,这里int是4个字节,所以加上1x4.
&a+1表示加上整个数组的大小,这里数组尺寸是4,所以+1代表的是地址加上4x4.
11.
斐波那契数列是指这样的一串数列:第一项、第二项为 1,从第三项开始,每一项为前两项之和,该数列的第𝑥项可以表示如下所示的函数。请根据描述,写出一个程序,使之输入𝑥后,能够输出斐波那契数列的第𝑥项(其中𝑥 ≤ 30)。当你完
成之后,你可以尝试使用递归解决这个问题。
1 , 𝑥 = 1 𝑜𝑟 𝑥 = 2
𝑓(𝑥) =
𝑓(𝑥 − 1) + 𝑓(𝑥 − 2) , 𝑥 ≥ 3 (𝑥 ∈ 𝑁ା)
#include<stdio.h>
int Fibonacci(int n){
if(n==1||n==2)
return 1;
else
return Fibonacci(n-1)+Fibonacci(n-2);
}
int main(){
int i;
scanf("%d",&i);
printf("%d",Fibonacci(i));
return 0;
}
12.
下面代码段是某一种排序算法的简单实现,你知道它是什么吗?请讲解其原理,并尝试改进它。你还知道哪些排序算法?试着详细描述这些算法。
void sort(int nums[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
if (nums[i] > nums[j])
{
int c = nums[i];
nums[i] = nums[j];
nums[j] = c;
}
}
}
}
冒泡排序
冒泡排序的基本思想是每次比较两个相邻的元素,如果它们的顺序错误就把它们交换.
改进1:n个数排序只需要进行n-1趟;
改进2:则设置flag变量,当某一次执行了一次排序之后所有元素位置都没有改变,使循环跳出.
改进代码如下:
#include<stdio.h>
#include<stdbool.h>
int main(){
int a[10];
int n;
int temp;
bool flag=true;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n-1&&flag;i++){
for(int j=0;j<n-1-i;j++){
flag=false;
if(a[j]>a[j+1]){
flag=true;
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
return 0;
}
13.
请简单叙述两种字节序(大端、小端)的概念,你的机器是什么字节序?试着写一个 C 语言程序来验证,如果你没有思路,你可以尝试着使用联合体或者指针。
字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处.
#include<stdio.h>
int main(){
short int x=0x1122;
char x0,x1;
x0=((char*)&x)[0];
x1=((char*)&x)[1];
printf("%#x",x0);
return 0;
}
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 3580 Nov 21 21:16 dev
drwxr-xr-x 83 root root 4096 Nov 21 22:12 etc
drwxr-xr-x 4 root root 4096 Sep 22 00:07 home
drwxr-xr-x 2 root root 4096 Aug 21 22:21 mnt
drwxr-x--- 9 root root 4096 Nov 19 19:15 root
dr-xr-xr-x 13 root root 0 Nov 21 21:15 sys
drwxrwxrwt 10 root root 380 Nov 21 22:30 tmp
drwxr-xr-x 9 root root 4096 Nov 21 22:12 usr
Linux ls命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录).
-al 指各项说明,查看设备是否具有读写权限.
第一列指文件类型及权限;
第二列指链接占用的节点;
第三列指文件所有者;
第四列指文件所有者的用户组;
第五列指文件大小;
第六列指文件的创建时间或者最近修改时间;
最后一列是文件名称.