十一、结构体,共用体的字节对齐
//64位系统 #include<stdio.h> union UNode{ char ch; int in; char *p; }; struct SNode{ char ch; short sh; int in; float f; double db; char *p; char arr[5]; union UNode UN; }; int main(){ printf("%d",sizeof(struct SNode));//48 printf("%d",sizeof(union UNode));//8 }
十二、逻辑选做题(可以不做)
ACAT2021纳新题(旧)
ACAT2021纳新题(旧)
说明:
本试题一共分为12道题,考核点全部以C语言为主,难度有层次划分,希望你尽最大努力完成,我们不需要你每道题都能得到正确答案,但希望你能有良好的学习态度。我们期待在面试那天与你相遇! (本测试题目省略#include…,编程题只用写出核心代码,你也可以在面试时带上U盘或者电脑直接展示你的结果!)
题目
参考
1. 请分析下列代码的运行结果,并解释其原因。
解析:考点:无 break 的 switch case 语句的执行流程
# include <stdio.h> int main() { int n=1,a=0,b=0; switch(n) { case 0://n=0跳过 b++; case 1://n=1进入 a++;//a变成1 //无break继续,不会跳出switch case 语句,继续向下执行 case 2: ++a;//a变成2 b++;//b变成1 } printf("a=%d,b=%d\n",a,b);// a=2,b=1 }
2.请分析下面函数的运行结果,并解释其原因
考点:带参数的宏定义 若修改为 #define S(r) PI*(r)*(r) 就是计算以x与y的和为半径的圆的面积
# include <stdio.h> #define PI 3 #define S(r) PI*r*r int main(){ float x,y,area; x=2; y=1; area=S(x+y);//S=PI*x+y*x+y=3*2+1*2+1=9 printf("r=%f\narea=%f\n",x+y,area);//r=3.000000 //area=9.000000 }
3.请分析下列代码的运行结果,并解释其原因。
考点:运算符的优先级和结合性 下表按照题目中运算符出现顺序排列
优先级 | 运算符 | 含义 | 结合性 |
15 | , |
逗号运算符 | 自左至右 |
2 | ++ |
自增运算符 | 自右至左 |
10 | ` | ` | |
14 | = |
赋值运算符 | 自右至左 |
2 | -- |
自减运算符 | 自右至左 |
注意:在逻辑表达式的求解中,并不是所有的逻辑运算符都要被执行,只有在必须下一个逻辑运算符才能求出表达式的解时,才执行该运算符。
例如: int x=-1; 执行++x||++x||++x后,x的值是多少? 分析:根据逻辑“||”自左至右的结合性,先计算第一个“”左边的运算对象++x,得到结果为0。 对于“||”运算符来说还不能确定这个表达式的值,必须再计算右边的++x,得到结果为1。 此时第一个“||”结合的表达式的值就为1,这样无论第二个“||”运算符后面的运算对象值为多少,整个表达式的值已经确定为1。所以不需再计算第三个++x了,因而x的值为1。
说回题目
int main(int argc, char const* argv[]) { int a = 0, b = 5; ++a || ++b, a - b;//a变成1 ||表达式的值为1,后面的++b不会执行 b = b--;//b=5 -- printf("%d %d\n", a, b);//1 5 return 0; }
4.请分析下列代码的运行结果,并解释其原因。
考点:运算符
# include <stdio.h> int main() { int a = 0;//a为0 int b = 0 == a;//0==a的值为1 ,b为1 int c = -1;//c为1 if (a = 1) {//a赋值为1 c = a && b;//c=1&&1=1 } printf("%d%d%d", a, b, c);//111 return 0; }
5. 分析下列代码,请计算 x,y,z的大小
考点:struct 的内存对齐
以下引用自https://blog.csdn.net/weixin_30432007/article/details/97729396
1、字节对齐的细节和编译器实现相关,但一般而言,如在windows下,就VC而言,满足一下三个准则: 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding); 即:在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量:sizeof(类型)或其倍数 3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding) 即:最大sizeof(类型)的整数倍
类型 对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量) Char 偏移量必须为sizeof(char)即1的倍数 int 偏移量必须为sizeof(int)即4的倍数 float 偏移量必须为sizeof(float)即4的倍数 double 偏移量必须为sizeof(double)即8的倍数 Short 偏移量必须为sizeof(short)即2的倍数
说回题目
# include <stdio.h> int main(){ struct x{ //16 2*8 int a; //4 Bytes ,此时偏移量为4 char b; //1 Byte ,偏移量4是1的倍数,此时偏移量为5 double c; //8 Bytes ,此时偏移量5不是8的倍数,填充3,使偏移量为8,然后为c开辟8个空间,此时偏移量为16 }; struct y{ //16 2*8 float b; //4 Bytes ,此时偏移量为4 int a; //4 Bytes ,偏移量4是4的倍数,此时偏移量为8 double c; //8 Bytes ,偏移量8是8的倍数,此时偏移量为16 }; struct z{ //24 3*8 int a; //4 Bytes ,此时偏移量为4 double c; //8 Bytes ,偏移量4不是8的倍数,填充4,此时偏移量为8,然后为c开辟8个空间,此时偏移量为16 char b; //1 Byte , 此时偏移量16是1的倍数,偏移量为17,结构体的总大小为结构体最宽基本类型成员大小的整数倍,即需是8的整数倍,需要编译器会在最末一个成员之后加上填充字节(trailing padding),填充8*3-17=7个,此时偏移量为24 }; printf("%d\n",sizeof(struct x)); //16 printf("%d\n",sizeof(struct y)); //16 printf("%d\n",sizeof(struct z)); //24 }
6.下面是一个交换两个变量的函数,看看这种方法可以实现吗?如果可以,还有其他方法吗?如果不可以,说说原因。
void swap(int a, int b) { int temp = a; a = b; b = temp; }
7.请分析以下代码的运行结果,并解释其原因。
考点:scanf的返回值的含义 scanf函数返回 int型 成功读入的数据项数, 读入数据时遇到了“文件结束”则返回EOF。
# include <stdio.h> int main() { int n; printf("%d", scanf("%d", &n));//输入非数值型为0,输入数值型为1 return 0; }
8.你知道哪些排序算法?你知道它们是怎样实现的吗?(大致思路)
9.字符串翻转
设计一个程序实现字符串翻转,即将abcdefg反转成gfedcba,已经为你写好了部分代码,请在规定的区域添加代码来实现程序。 不允许在规定地方之外写代码,不允许删除写过的代码。 代码本来就定义了一个字符串和一个字符变量和一个整型数,不允许声明新的任何类型的变量。
考点:字符串翻转 要求:空间复杂度为O(1),即不允许声明新的任何类型的变量。 实现:字符串内部操作
# include <stdio.h> # include <string.h> int main() { char s[32]; scanf("%s", s); int n = strlen(s); int i; char ch; /* 规定区域开始 */ for(i = n-1;i>=n/2;i--){ ch=s[n]; s[n]=s[n-i]; s[n-i]=ch; } /* 规定区域结束 */ printf("%s", s); return 0; }
补充用递归实现
#include<stdio.h> void reverseSentence(); int main(){ printf("输入:"); reverseSentence(); return 0; } void reverseSentence(){ char c; scanf("%c",&c); if(c != '\n'){ reverseSentence(); printf("%c",c); } }
10.水仙花数
“水仙花数”是指一个三位数其各位数字的立方和等于该数本身, 例如153是“水仙花数”,因为:153 = 13 + 53 + 33, 所以判断一个数是否为“水仙花数”,最重要的是要把给出的三位数的个位、十位、百位分别拆分,并求其立方和(设为s), 若s与给出的三位数相等, 三位数为“水仙花数”,反之,则不是。 请你编写一段代码,判断一个三位数数是否是水仙花数。
11.打印杨辉三角形
输入一个任意正整数n,请你编写一段代码,打印n行的杨辉三角形。 例:n = 4 输入结果: 1 1 1 1 2 1 1 3 3 1
12.逻辑图
哲学家就餐问题是在计算机科学中的一个经典问题 哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。 吃东西的时候,他们就停止思考,思考的时候也停止吃东西。 餐桌中间有一大碗米饭,每两个哲学家之间有一只筷子。 哲学家想要吃饭必须拿到两个筷子。 哲学家从来不交谈,这就很危险。 有可能导致什么情况呢? 每个哲学家都拿起来自己左手边的筷子,然后眼巴巴地等着自己右边的哲学家放下筷子好让自己集齐一双筷子来吃饭。 请问如何避免这种现象发生呢?(想法越多越好)