整理了一下一些错题,以便日后回顾。
考试错题
编程实现一个对8bit数据(unsigned char)的指定位(比如第n位)的置0或者置1操作,其他位保持不变。
函数原型:
void bit_set(unsigned char *p_data, unsigned char pos, int flag)
这道题考试的时候我是这么写的:将这个p_data左移、右移。刚才在写关于位段的错题时,想起来还可以这么搞,但是还是移位操作比较方便,嘿嘿,我就试试。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
typedef struct sup
{
unsigned char uc1 : 1;
unsigned char uc2 : 1;
unsigned char uc3 : 1;
unsigned char uc4 : 1;
unsigned char uc5 : 1;
unsigned char uc6 : 1;
unsigned char uc7 : 1;
unsigned char uc8 : 1;
} *pSUP_S;
void bit_set(unsigned char *p_data, unsigned char pos, int flag)
{
pSUP_S ps = (pSUP_S)p_data;
switch(pos)
{
case 1:
ps->A(uc, 1) = flag;
break;
case 2:
ps->A(uc, 2) = flag;
break;
case 3:
ps->A(uc, 3) = flag;
break;
case 4:
ps->A(uc, 4) = flag;
break;
case 5:
ps->A(uc, 5) = flag;
break;
case 6:
ps->A(uc, 6) = flag;
break;
case 7:
ps->A(uc, 7) = flag;
break;
case 8:
ps->A(uc, 8) = flag;
break;
default:
break;
}
}
void print(unsigned char a)
{
while(a)
{
printf("%d", a%2);
a /= 2;
}
printf("\n");
}
int main()
{
unsigned char a = 1;
bit_set(&a, 5, 1);
print(a);
return 0;
}
给出以下定义:
char x[] = "abcdefg";
char y[] = {'a','b','c','d','e','f','g'};
则正确的叙述为(C)
A)数组x和数组y等价 B)数组x和数组y的长度相同
C)数组x的长度大于数组y的长度 D)数组x的长度小于y的长度
分析:粗心大意!选项都不看清就选答案?
设有如下定义:
unsigned long arr[] = {6,7,8,9,10};
unsigned long *p;
则下列程序段的输出结果为(6,12)
1
2
3p = arr;
*(p + 3) += 3;
printf("%d,%d\n", *p, *(p + 3));分析:粗心大意!慌什么慌,稳住啊。给数组解引用又不是给你解引用,题看完再写啊。
全局变量可以定义在被多个.c文件包含着的头文件中(❌)
分析:注意区分定义和声明的概念,definition、declaration!
下面这道题虽然没错,但是还是想写出来,自己以后看到也注意点,别忘了。
1
2
3
4
5unsigned char a = 200;
unsigned char b = 100;
unsigned char c = 0;
c = a + b;
printf("%d %d ",a+b,c);C的整型算数运算总是至少以缺省整型类型的精度来进行的,为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换为普通整型。《C和指针》
分析:输出结果为
300,44
,注意整形提升问题,整形提升笔记
下面这个题也是粗心大意造成的,但是还是有一点就是没有区分清楚指针数组和数组指针等概念。关于指针的笔记
1
2
3
4
5
6
7
8unsigned short *pcArr[10][10];
typedef union unRec
{
unsigned long a;
unsigned short b[7];
unsigned short c;
}REC_S;
REC_S stMax, *pstMax;当四字节对齐方式时:
sizeof(pcArr) = 400
,是一个10•10的指针数组,数组里存放的是指针。sizeof(stMax) = 16
,注意这里是union,慌什么!?sizeof(pstMax) = 4
,指针的大小sizeof(*pstMax) = 16
,钥匙(&)重4kg,拿着钥匙进了你家门。
结构体定义如下:
1
2
3
4
5
6
7
8
9struct B
{
long l1;
char c2;
char c3;
long l4;
long l5;
} *p;
p = (struct B*)0x100;p + 0x1 = 0x110
,结构体大小是16,指针p的一步长为16,向前走一步加16(10H)。(unsigned long)p + 0x1 = 101
,注意是强转成了一个数。(unsigned long *)p + 0x1 = 0x104
,强转成了指针。
有如下定义:
1
2
3
4
5
6
7
8
9
10struct A
{
unsigned char uc1 : 1;
unsigned char uc2 : 2;
unsigned char uc2 : 6;
unsigned char uc3 : 4;
unsigned char uc4;
unsigned char uc5 : 4;
unsigned char uc6;
} AAA_S;问:AAA_S在1字节对齐和4字节对齐的情况下,占用的空间大小是:6字节、12字节
分析:对于结构体内存对齐这块掌握的还是不好,也没有整理过笔记什么的,考完试整理一篇笔记,复习复习(预习)。
以下程序的执行结果为:2 29 0 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(int argc, char const *argv[])
{
unsigned char puc[4];
struct tagPIM
{
unsigned char ucPiml;
unsigned char ucData0 : 1;
unsigned char ucData1 : 2;
unsigned char ucData2 : 3;
} *pstPimData;
pstPimData = (struct tagPIM *)puc;
memset(puc, 0, 4);
pstPimData->ucPiml = 2; // 2-> 10b
pstPimData->ucData0 = 3;// 3-> 11b
pstPimData->ucData1 = 4;// 4-> 100b
pstPimData->ucData2 = 5;// 5-> 101b
printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]);
return 0;
}分析:首先,结构体tagPIM占4个字节,puc[0]-puc[3]分别指向这4个字节,并初始化为了0,但是tagPIM只用了前两个字节,所以puc[2]和puc[3]的输出结果为0,其余的如下图分析:
要注意的几点:第一、ucData0放3(11b)的时候,从低地址开始放,放不下的扔掉,对于ucData1也是。第二、要注意是小端,输出结果的时候是从右往左看的二进制数,还要注意输出的是以16进制的形式输出。
注意函数传递的时候,形参的问题。
添加下面分割线内的代码的初衷是为了给
gui_show_image
这句代码的执行加上限制条件,请问这样修改有没有隐患,若有,该如何修改?1
2
3
4
5
6
7
8
9
10
11
12
13// ......
gui_push_clip();
/*我是分割线*/
if (show_status == MMI_TRUE)
/*我是分割线*/
gui_show_image(x, y, image_id);
gui_pop_clip();
update_dt_display();
// ......分析:这句话我第一眼看没啥啊,仔细看🧐下:如果宏BBB没有被定义,程序的逻辑就变成了下面这样:
1
2if (show_status == MMI_TRUE)
gui_pop_clip();修改的方法:加大括号,要养成良好的编码习惯。
牛客的错题整理
双链表中至多只有一个节点的后继指针为空(🙆♂️)
非循环双链表最后一个节点的后继指针为空;循环双链表没有一个节点的后继指针为空。
一个长度为99的循环链表,指针A和指针B都指向了链表中的同一个节点,A以步长为1向前移动,B以步长为3向前移动,一共需要同时移动多少步A和B才能再次指向同一个节点?(99)
我选的50,但并不是50,首先是个循环链表,再来就是只有99个元素,设A走x步,那么B走3x步,两个碰到需要$(3x-x) MOD 99 = 0$,x取99才满足。
在有n个结点的二叉链表中,值为非空的链域的个数为(n-1)
值为空的链域个数为n+1个,为非空的个数为n-1个。
向一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变,平均要移动(63.5)个元素。
插入:$\frac {n}{2}$,删除:$\frac {n-1}{2}$,查找:$\frac {n+1}{2}$
广义表第一个元素是表头,其余元素是表尾,如果只有一个元素,那么表尾为空即
()
,在广义表中注意区分空表和有一个为空表的元素的情况。广义表有如下三个特性:1.层次性:广义表的元素可以是子表,而子表的元素还可以是子表,由此,广义表是一个多层次的结构。2.共享性:广义表可为其他表所共享。3.递归表:广义表可以是其自身的一个子表。
十字链表是无向图的一种存储结构(🙅♂️)。
无向图存储:邻接矩阵、邻接表、多重邻接表。有向图存储:邻接矩阵、邻接表、十字链表
荐读:《C++/C高质量编程指南》、《C语言深度剖析》