- 选择题(10)
- 填空题(8)
- 编程题(1)
- 总结
- 1.以下循环执行次数是1次的是( C )。
A. for(int i = 10, j = 1; i = j = 0; i++, j--)
B. do
{
}while(0)
C. int i = 1;
while(i--)
{
}
D. unsigned char i;
for(i = 255; i < 256; i++)
- 解释
A. for循环中的判断语句i=j=0,写成了赋值语句,因此该处的判断为false,不循环。
B. 循环一次,但是代码会报错,while(0)后面少一个分号。
C. ✔。
D. char的范围是0-255,因此条件一直成立,上述为死循环。
- 2.以下说法正确的是(B)。
A. break语句只用于循环体中。
B. continue语句只用于循环体中。
C. break是无条件跳转语句,continue不是。
D. break和continue的跳转范围不够明确,容易产生问题。
- 解释
A. break还可用于switch…case…。
B. ✔。
C. 两者都为无条件跳转,另外goto和return也是。
D. 是明确的,break跳出当前循环,continue跳出本次循环,执行下一次循环。
- 3.64位系统以及64位编译器下,下面的代码输出中哪写正确(AD)。
void fun(int str[])
{
int a = sizeof(str);
}
int temp[10] = {1, 2, 3};
int b = sizeof(temp);
fun(temp);
A. a = 8。
B. a = 40。
C. b = 12。
D. b = 40。
- 解释
b是10个int所占的字节,一个int占4个字节,a为指针,为8字节。
- 4.题未知
- 5.下面程序片段的输出是(A)。
int a[] = {1, 2, 3, 4, 5};
int *ptr = (int*)(&a + 1);
print("%d, %d", *(a + 1), *(ptr - 1));
A. 2, 5。
B. 2, 1。
C. 1, 2。
D. 5, 1。
- 解释
(a + 1)表示数组的第二个数,a为首地址,&a也为首地址,星号表示从地址解析出值。
&a+1,与上表示不一样,加一表示加上a数组的长度,如以下程序中的第四行输出结果,首地址为6422016,&a+1为6422036,在首地址上加了4 * 5 = 20个字节,若是加&a+2,则加上40。(ptr-1),减1,是减少4个字节,int的话,就是向前移动一个数字,所以第二个答案是5,减2的话答案就是4了。
另外
如果数组是char类型的,一个char占一个字节,*(ptr-1)中的减1,也是减少四个字节,但是主义char类型的有结束符号,因此减一后的答案是3。
int main()
{
int a[] = {1, 2, 3, 4, 5};
//char a[] = "12345";
int *ptr = (int*)(&a+1);
printf("res: %d, %d\n", *(a+1), *(ptr-1));
printf("%d, %d\n", (a+1), (ptr-1));
printf("a: %d, a+1: %d\n", a, a+1);
printf("&a: %d, &a+1: %d\n", &a, &a+1);
printf("a: %d, ptr: %d", &a+1, ptr);
return 0;
}
//结果
res: 2, 5
6422020, 6422032
a: 6422016, a+1: 6422020
&a: 6422016, &a+1: 6422036
a: 6422036, ptr: 6422036
- 6.假设有一颗二叉树的后序遍历为DBFEGCA,中序遍历为DBAFECG,则先序遍历为(A)。
A. ABDCEFG。
B. ADCBEFG。
C. ADBFEGC。
D. ABDCFEG。
- 解释
后序遍历,(左子树)(右子树)(根节点)。
中序遍历,(左子树)(根节点)(右子树)。
前序遍历,(根节点)(左子树)(右子树)。
树的重建:先重前或者后序遍历中寻找根节点(前序中第一个就是根节点,后序中最后一个是根节点),然后再中序遍历中找出左子树和右子树,再重复以上 *** 作,即可恢复二叉树。
- 7.进程间通信(IPC)的方法有()。
A. 匿名通道。
B. 有名通道。
C. 条件变量。
D. 共享内存。
E. 互斥量。
- 解释
进程间通信有:管道(匿名管道,命名管道),消息队列,信号量,信号,共享内存,Socket
详细解释参考这里
- 8.数字推理:1/17, 1/7, 4/11, 1 (B)
A. 15。
B. 16/5。
C. 8。
D. 7/2。
- 解释
将数展开成:1/17, 2/14, 4/11, 8/8, 16/5
分子为2的次方,1 2 4 8 16 32
分母依次减三
- 9.题未知
- 10.题未知
- 1.CPU执行一段程序时,cache完成存取的次数为2500次,主存完成存取的次数为625次,已知cache存取周期为30ns,主存为180ns,求cache、主存系统的效率和平均访问时间 60 ns。
- 解释
存取总次数:2500+625 = 3125
命中率:H = 2500 / 3125 = 0.8
主存慢于cache的倍率:r = 180 / 30 = 6
访问效率:e = 1 ( r + ( 1 − r ) H ) \frac{1}{(r + (1-r)H)} (r+(1−r)H)1 = 1 ( 6 + 0.8 ∗ ( − 5 ) ) \frac{1}{(6 + 0.8*(-5))} (6+0.8∗(−5))1 = 50%
平均访问效率:T = t/e = 30ns/50% = 60ns
- 2.以下程序打印的结果(m = 5, n = 6)
#include
int main()
{
int i = 2, j = 5, m = 0, n = 0;
if ((i = 1)||(j != 5)) m = 5;
else m = 6;
if ((i & j) != 1) n = 5;
else n = 6;
}
- 解释
在第一个if语句中,i = 1为赋值语句,且为true,故m = 5。
在第二个if语句中,i = 1(001), j = 5(101),两个相与,结果为001,故判断结果为false,n = 6。
-
3.定义一个返回值类型为bool,有一个int型参数a的纯虚函数func:
virtual bool func(int a) = 0; -
4.派生类覆盖基类的虚函数,实现接口的重用,且返回值类型相同,称为函数的重写;将语意相近的几个函数用同一个名字表示,但是参数列表(参数的类型,个数,顺序)不同,成为函数的重载。
-
5.写出四种进程间通信方式:
消息队列, 信号量,信号,Socket,内存共享,管道。 -
6.p为无符号整型数据,len为p数组长度,请完成空白处程序,如存在p的低16位为零,高16位不为零返回1,否则返回0.
int fun(unsigned int *p, int len)
{
for(int i = 0; i < len; i++)
{
if ==((p & 0x0000FFFF == 0) && (p & 0xFFFF0000) != 0)==
{
return 1;
}
p++;
}
return 0;
}
int main()
{
int res = 0;
unsigned int test[] = {{0x34e20000,0x005600ff,0x1000fee3, 0x00002380};
res = fun(&test[0], ==sizeof(test) / sizeof(test[0])==);
}
- 解释
上述代码中“====”中间的为所填的程序
((p & 0x0000FFFF == 0) && (p & 0xFFFF0000) != 0)
sizeof(test) / sizeof(test[0])
- 7.采用64位的编译器,下面程序的结果是d1 = 16, d2 = 4, d3 = 8。
struct da1{
int a;
char *b;
}
struct da2{
int a;
char b[0];
}
struct da3{
int a;
char b[1];
}
int main()
{
struct da1 d1;
struct da2 d2;
struct da3 d3;
printf("d1 = %zd", sizeof(d1));
printf("d2 = %zd", sizeof(d2));
printf("d3 = %zd", sizeof(d3));
}
- 解释
8+8 = 16, 4+0 = 4, 4+4 = 8。
- 结构体成员的偏移量必须是当前成员大小的整数倍
- 结构体的大小必须满足所有成员(不考虑数组和内套结构体)的整数倍
- 注意最后的结果不考虑结构体成员中数组大小的整数倍
结构体的大小结算参考这里,变量占字节大小参考这里。
- 8.使用冒泡排序(我感觉题错了,应该是选择排序叭)从小到大,修改下面程序的错误。
void sort(int *p, int n)
{
int *q, *k;
for (q = p; q < p + n -1; q++){
for (k = q + 1; k < p + n; k ++){
if (*k < *q){
int t = q; //1
*q = *k;
*k = t;}}}
return 0; //2
}
int main()
{
int len = 7;
int arr[len] = {23, 34, 46, 43, 86, 57, 22};
sort(&arr, len); // 3
for(int i = 0; i < 7; i++) printf("%d ", *arr+i); // 4
return 0;
}
int t = q; -> int t = *q;
return 0; -> return ;
sort(&arr, len); -> sort(arr, len);
printf("%d “, *arr+i); -> printf(”%d ", *(arr+i));
修改后程序
void sort(int *p, int n)
{//选择排序
int *q, *k;
for (q = p; q < p + n -1; q++){
for (k = q + 1; k < p + n; k ++){
if (*k < *q){
int t = *q; //1
*q = *k;
*k = t;}}}
return ; //2
}
int main()
{
int len = 7;
int arr[len] = {23, 34, 46, 43, 86, 57, 22};
sort(arr, len); // 3
for(int i = 0; i < 7; i++) printf("%d ", *(arr+i)); // 4
return 0;
}
编程题(1)
给定一个循环链表,删除其中的一个节点,在返回一个任意节点。
请定义函数:pnode delete_node(pnode list, pnode node)
数据节点为
typedef struct n
{
int data;
struct n *next;
} *pnode;
参考这里
pnode delete_node(pnode list, pnode node)
{
//循环遍历循环链表,当下一个节点指向头结点时,表示遍历完
Pnode cur;
Pnode target;
if(cur == NULL)
{
print(“这是个空指针,无法删除”)
return NULL;
}
if (list == node)
{//删除头结点
//寻找尾节点target
for(target = list; target->next != list; target = target->next);
cur = list; //存下头结点
list = list->next; //记录开始节点的下一个
target->next = list; //最后一个节点指向下一个节点
free(cur); //删除节点
return list
}
else
{//删除其他节点
for(target = list; target->next != node && target->next != list; target = target->next);
//找到了node,则target是node的前一个节点,找到不到的话,则target和头节点相等
if(target->next == list)
{
//没有寻找的节点,返回头结点
return list;
}
else
{//找到node节点了
//删除中间的节点, 则找该节点的前一个节点target
cur = target->next;
target->next = target->next->next: //
free(cur); //删除尾节点
return list;
}
}
}
总结
总的来说,还是挺基础的,考的比较细,但是不好做,当时做的可差了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)