2021西邮linux兴趣小组纳新题题解
1. 大小和长度竟然不是一个意思
sizeof()
和strlen()
有什么异同之处?他们对于不同参数的结果有什么不同?请试举例子说明。
int main(void) {char s[] = "I love Linux\0\0\0";int a = sizeof(s);int b = strlen(s);printf("%d %d\n", a, b);
}
- 程序输出为
16 12
- sizeof会统计字符串结尾的\0;而strlen不会,它只统计\0之前的字符串个数,遇到\0停止
- 因此sizeof的结果比strlen的多能看见的三个\0,以及在字符串末尾自动加上的再一个\0,即一共多四个\0。So,16和12相差4
举个栗子ヾ(•ω•`)o
int main(){char arr1[]="abc";char arr2[]={'a','b','c'};printf("%d\n"sizeof(arr1));printf("%d\n"sizeof(arr2));printf("%d\n"strlen(arr1));printf("%d\n"strlen(arr2));
}
- 根据以上的说明,可知该程序的输出为
4 3 3 26(随机值)
(由于arr2没有结尾的\0,所以计算完‘c’后,继续往后计算,直到遇见随机的\0) - 嗯哼,没看够?点这里
注意:
- sizeof是运算符,计算对应类型所占的空间数,不是函数;而strlen是在#include<string.h>头文件下的一个计算字符串长度的函数,且只能(char*)字符串作为参数
2. 箱子的大小和装入物品的顺序有关
test1
和test2
都含有:1个short
、1个int
、1个double
,那么sizeof(t1)
和sizeof(t2)
是否相等呢?这是为什么呢?
struct test1 {int a;short b;double c;
};
struct test2 {short b;int a;double c;
};
int main(void) {struct test1 t1;struct test2 t2;printf("sizeof (t1) : %d\n", sizeof(t1));printf("sizeof(t2): %d\n", sizeof(t2));
}
- 相等,均为
16
- 了解一下结构体的内部成员存放和结构体的大小:
1.结构体内部的成员不是连续紧挨着存放的
2.结构体可以分成N份,每份的大小是最大成员类型的长度
3.结构体的大小为N * 最大成员类型的长度
再看这题:
- 举该题t1的例子,由于double是占了8个字节,为结构体成员中的最大长度,因此
每份大小为8
; - 第一份中,int占了4个字节,还剩8-4=4个字节,
∵4>2(shout)
,∴
接下来的short可以继续放在第一份中,此时第一份里只剩下8-4-2=2个字节,∵2<8(double)
,∴
double无法再放入第一份,得重开新的第二份; - 第二份刚好放下double;
- 在这个结构体中
一共用了两份
,所以结构体大小为8(每份大小)× 2(份数)=16
3. 哦,又是函数
想必在高数老师的教导下大家十分熟悉函数这个概念。那么你了解计算机程序设计中的函数吗?请编写一个
func
函数,用来输出二维数组arr
中每个元素的值。
/*在这里补全func函数的定义*/
int main(void) {int arr[10][13];for (int i = 0; i < 10; i++) {for (int j = 0; j < 13; j++) {arr[i][j] = rand();}}func(arr);
}
- 上代码
void fun( int a[][13] ){int i ,j;for( i = 0 ; i < 10 ; i++ ){for( j = 0 ; j < 13 ; j++ ){printf( "%d" , a[i][j] );}}
}
- over
4.就不能换个变量名吗?
- 请结合下面的程序,简要谈谈
传值
和传址
的区别。- 简要谈谈你对C语言中变量的生命周期的认识。
int ver = 123;
void func1(int ver) {ver++;printf("ver = %d\n", ver);
}
void func2(int *pr) {*pr = 1234;printf("*pr = %d\n", *pr);pr = 5678;printf("ver = %d\n", ver);
}
int main() {int a = 0;int ver = 1025;for (int a = 3; a < 4; a++) {static int a = 5;printf("a = %d\n", a);a = ver;func1(ver);int ver = 7;printf("ver = %d\n", ver);func2(&ver);}printf("a = %d\tver = %d\n", a, ver);
}
看结果:
传值:把A的数值传到B,改变B,A不会跟着变,B存的是跟A一样的值
传址:把A的地址传到B,改变B,A同时跟着变,B存的是A的地址
生命周期:将一对大括号称为“块”
1.本地变量定义在块内,且不会被默认初始化(因此第一个的输出结果为随机值)
2.程序运行到“块”之前,其中的变量不存在;离开“块”,其中的变量消失了
3.“块”外面定义的变量其一下到处有效
4.“块”里面定义了和外面同名的变量,则会掩盖外面的据以上信息,便可得其结果
5. 套娃真好玩!
请说明下面的程序是如何完成求和的?
unsigned sum(unsigned n) { return n ? sum(n - 1) + n : 0; }
int main(void) { printf("%u\n", sum(100)); }
结果为
5050
=100+99+…+1本题了解条件运算符的执行方法就能解决
6. 算不对的算术
void func(void) {short a = -2;unsigned int b = 1;b += a;int c = -1;unsigned short d = c * 256;c <<= 4;int e = 2;e = ~e | 6;d = (d & 0xff) + 0x2022;printf("a=0x%hx\tb=0x%x\td=0x%hx\te=0x%x\n", a, b, d, e);printf("c=Ox%hhx\t\n", (signed char)c);
}
又双叒叕是位运算
注:图片来自位运算全面总结,关于位运算看这篇就够了
%hx
代表以16进制输出short类型的整数,因此a,b显而易见,不解释- 关于d,d为无符号的short,c*256=-256,所以此时d=216+(-256);接着d和0xff进行与运算,结果为0,再加上0x2022,所以d最终=
0x2022
- 关于e,先进行 ~(取反),取反结果和6进行或运算,结果为
0xffffffff
- 关于c,将c左移4位后,并强制类型转换成signed char,得
0xfff0
7. 指针和数组的恩怨情仇
int main(void) {int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};int(*b)[3] = a;++b;b[1][1] = 10;int *ptr = (int *)(&a + 1);printf("%d %d %d \n", a[2][1], **(a + 1), *(ptr - 1));
}
- 结果:
10 4 9
int main(void) {int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};int(*b)[3] = a;//b和*结合,构成一个名为b指针,int修饰数组的内容(数组的每个元素),因此b指针指向该数组的首地址,//而这个数组有3个单元,每个单元都是int类型,且该数组没有名字>>指向含有3个int数组的指针//将a赋值给他,使b指针指向a数组第一个单元{1,2,3}中的首元素1++b;//指针b指向a数组的第二个单元{4,5,6}中的首元素4b[1][1] = 10;//经过++b后,b[0][0]为4,所以这里的b[1][1]为8,并将其赋值为10(即a[2][1]=10)int *ptr = (int *)(&a + 1);//(&a+1)是指针ptr指向a数组的下一个数组(在a数组最后一个元素的后面)printf("%d %d %d \n", a[2][1], **(a + 1), *(ptr - 1));
}
- a[2][1]据分析可得为10
- **(a + 1)可理解为 * (*(a+1)+0)=a[1][0]=4
- *(ptr - 1))指整个数组的下一个数组减去一个元素地址,得到上一个数组a的最后一个元素9
- a+1和&a+1的区别
8. 移形换位之术
下面有
a
、b
、c
三个变量和4个相似的函数。
- 你能说出使用这三个变量的值或地址作为参数分别调用这5个函数,在语法上是否正确吗?
- 请找出下面的代码中的错误。
const int
和int const
是否有区别?如果有区别,请谈谈他们的区别。const int *
和int const *
是否有区别?如果有区别,请谈谈他们的区别。
int a = 1;
int const b = 2;
const int c = 3;
void funco(int n) {n += 1;n = a;
}
void func1(int *n) {*n += 1;n = &a;
}
void func2(const int *n) {*n += 1;n = &a;
}
void func3(int *const n) {*n += 1;n = &a;
}
void func4(const int *const n) {*n += 1;n = &a;
}
void func2(const int *n) {//const修饰指针*n,表示*n指向的值不能被改变*n += 1;//因此这里是错误的n = &a;
}
void func3(int *const n) {//const修饰地址,表示指针的地址不能被改变*n += 1;n = &a;//因此这里是错误的
}
void func4(const int *const n) {//const修饰指针和地址,两者均不能改变*n += 1;//因此这里是错误的n = &a;//因此这里是错误的
}
- const int和 int const都表示int类型的变量不能被修改
const int *a
、int const *a
:(*和a连在一起)表示指针a指向一个const int,即 *a的值为const,不能被修改- 而对于
int *const a
:(* 和a分开来了)表示地址固定的指针a不能被修改地址,但能修改*a的值 - 更多见:here here
9. 听说翻转字母大小写不影响英文的阅读?
请编写
convert
函数用来将作为参数的字符串中的大写字母转换为小写字母,将小写字母转换为大写字母。返回转换完成得到的新字符串。
char *convert(const char *s);
int main(void) {char *str = "XiyouLinux Group 2022";char *temp = convert(str);puts(temp);
}
- 上代码
char *convert(const char *s)
{int len=strlen(s);char *a=(char*)malloc(len);strcpy(a,s);char *q=a;for(;*a!='\0';a++){if(*a>='a'&&*a <= 'z') *a -= 32;else if(*a >= 'A'&&*a <= 'Z') *a += 32;}return q;
}
10. 交换礼物的方式
- 请判断下面的三种
Swap
的正误,分别分析他们的优缺点。- 你知道这里的
do {...} while(0)
的作用吗?- 你还有其他的方式实现
Swap
功能吗?
#define Swap1(a, b, t) do { t = a; a = b; b = t; } while (0)
#define Swap2(a, b) do { int t = a; a = b; b = t; } while (0)
void Swap3(int a, int b) {int t = a;a = b;b = t;
}
- swap1、2正确,swap3错误
swap1:
直接从原函数中传递参数,方便快捷swap2:
在参数中创建交换变量t,作用时间短,且占用内存空间小swap3:
只传递了a,b变量的值而并没有传递地址,所以仅在函数内部改变了a,b的值而函数作用完后就释放掉函数中变量的内存,a,b的值还是没有改变- do {…} while(0)的作用:实现局部作用域(为了在宏定义中使用多个语句块而不会受大括号和分号的影响)
- 用指针啦
11. 据说有个东西叫参数
你知道
argc
和argv
的含义吗?请解释下面的程序。你能在不使用argc
的前提下,完成对argv
的遍历吗?
int main(int argc, char *argv[]) {printf("argc = %d\n", argc);for (int i = 0; i < argc; i++)printf("%s\n", argv[i]);
}
- argc:外部输入的参数个数
- argv:参数的字符串数组,用来存放指向字符串参数的指针数组
- (argc=1时,表示只有一个程序名称,存储在argv[0]中;argv[0]指向程序运行的全部路径名;argv[1]指向程序在DOS命令中执行程序名的第一个字符串,后面以此类推)
- 见代码
int main(int argc, char *argv[]) {printf("argc = %d\n", argc);for ( int i = 0; argv[i]!='\0'; i++)printf("%s\n", argv[i]);
}
一样的结果:
12. 人去楼空
这段代码有是否存在错误?谈一谈静态变量与其他变量的异同。
int *func1(void) {static int n = 0;n = 1;return &n;
}
int *func2(void) {int *p = (int *)malloc(sizeof(int));*p = 3;return p;
}
int *func3(void) {int n = 4;return &n;
}
int main(void) {*func1() = 4;*func2() = 5;*func3() = 6;
}
- 解答见下
int *func3(void) {int n = 4;return &n;//不可返回局部变量的地址(&n),作用完就被释放了
}
- static int 与 int 的区别:
static int
不管在函数内还是函数外,都作为一个全局变量可以保存它被修改以后的值。而int
则没有这一功能,只有作为全局变量时能保存修改。 - c语言中static关键字用法详解
13. 奇怪的输出
int main(void) {int data[] = {0x636c6557, 0x20656d6f, 0x78206f74,0x756f7969, 0x6e694c20, 0x67207875,0x70756f72, 0x32303220, 0x00000a31};puts((const char*)data);
}
- 这里涉及到一个知识点:大端法,小端法
- 在了解这个之前,先了解一个专业词:字节序。字节序,顾名思义就是字节的排列顺序,而计算机中既可以从高位到低位进行排列,也能从低位到高位进行排列
- 现在再来看大端法、小端法:假设有数据0x12345678,左边为高字节,右边为低字节。将高字节的数据放在低地址,便是大端法;反之,为小端法
- 下图,上面一排为字节的存放地址,从左到右,地址由低到高;下面一排为字节,分别存放在不同的地址中
大端法
小端法
- 一般家庭计算机所使用的为小端法,因此根据以上知识并查阅阿斯克码表可得,该程序的输出为
Welcome to xiyou Linux group 2021
14. 请谈谈对从「C语言文件到可执行文件」的过程的理解
- 图片来自谈谈C语言从源文件变为可执行文件之间发生的过程详解(C程序的编译链接运行)
全题终。。。。。。
点个赞再走呗ヾ(•ω•`)o
2022西邮linux兴趣小组纳新题题解
2021西邮linux兴趣小组纳新题题解相关推荐
- 2020西邮linux兴趣小组纳新题题解
1. 请试着解释其输出. int main(int argc , char *argv[]) {unsigned char a = 255;char ch = 128;a -= ch;printf(& ...
- 2021西邮linux兴趣小组纳新题解
目录 1. 请试着解释其输出 2. 下面代码的运行输出结果是什么,并说说你的理解. 3. 这段代码的输出结果是什么?为什么会出现这样的结果? 4. 下面程序会出现什么结果?为什么会出现这样的结果? 5 ...
- 2021年 西邮Linux兴趣小组 纳新免试题揭秘
文章目录 引言 第一关 第二关 第三关 第四关 第五关 总结 引言 小组2020年的免试题的四位出题人是:小组18级成员李兆龙,20级成员赵子玮,刘树杭,任子涧. 同时19级成员周阔,戚凯萌,胡哲宁, ...
- 西邮Linux兴趣小组纳新笔试试题
下面是西邮Linux小组今年纳新的笔试试题 1. 下面这个程序的输出结果是什么? int main() { int a = (1, 2); printf("a = %d\n", a ...
- 西邮linux兴趣小组网络,西邮Linux兴趣小组纳新笔试试题
下面是西邮Linux小组今年纳新的笔试试题,原文在这里. 1. 下面这个程序的输出结果是什么? int main() { int a = (1, 2); printf("a = %d\n&q ...
- 西邮linux面试题,西邮Linux兴趣小组纳新免试题! come on!
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 密文: 0011011101111010101111001010111100100111000111000000000000000011100110111 ...
- 2022西邮linux兴趣小组纳新题解
目录 0. 我的计算器坏了?! 1. printf还能这么玩? 2. 你好你好你好呀! 3.换个变量名不行吗? 4. 内存对不齐 5. Bitwise 6. 英译汉 7. 汉译英 8. 混乱中建立秩序 ...
- 西邮linux兴趣小组网络,西邮Linux兴趣小组2012纳新笔试题
这是我们西邮Linux兴趣小组2012的纳新笔试题,对于大一的学生,出得有难度哦,个人感觉比腾讯实习生的笔试题出的有水平. 西邮Linux兴趣小组纳新试题 姓名: ...
- 西邮Linux兴趣小组2021纳新面试题题解
注: 本题目仅作西邮Linux兴趣小组2021纳新面试题的有限参考. 为节省版面本试题的程序源码中省略了#include指令. 本试题中的程序源码仅用于考察C语言基础,不应当作为C语言代码风格的范例. ...
最新文章
- ISP、主机之间的通信方式、电路交换和分组交换、时延
- 主线程等待线程池所有任务完成
- myeclipse中添加Oracle数据库
- c语言错误解析-变量声明
- 2017.6.5 YY的GCD 失败总结
- 面向对象设计模式纵横谈:Prototype 原型模式(笔记记录)
- 引用 DetachedCriteria
- 简单谈谈视频网站分析
- git revert与git reset
- 0903 - Firebase Analytics PK Google Analytics
- 生物医学基础--人体阻抗模型
- GSM模块通过服务器或GSM内部获取网络时间 网络授时
- ABT Node:为去中心应用开发带来的范式迁移
- Pinia学习笔记之--核心概念Actions
- ACM与IEEE双Fellow、华人女计算机科学家周以真:可信 AI,未来可期
- Mac 苹果系统没有WIFI选项自检出现-1005D
- python interpreter配置_PyCharm使用之配置SSH Interpreter
- 1. 树莓派的基础配置
- 线性回归使用的基本条件
- 小程序毕业设计 基于微信电影院购票小程序毕业设计开题报告功能参考