10 嵌入式软件面试 — 代码检查
10.1 编写代码
问题1:写出float x与“零值”比较的if语句
if(x > -0.000001 && x < 0.000001);
解读:因为计算机在处理浮点数的时候是有误差的,所以不能将浮点型变量用“==”或“!=”与数字比较,应该设法转化成“>”或“<”此类形式。
问题2:强制类型转换
给了一个地址a,分别强转类型为:int变量、int指针、数组指针、指针数组、函数指针。
(int) a; //int变量 (int *)a; //int指针 (int (*)[])a; //数组指针 (int *[])a; //指针数组 (int (*)(int))a; //函数指针
10.2 代码输出
问题3:代码输出1
void foo(void) { unsigned int a = 6; int b = -20; (a + b > 6)? printf("> 6") : printf(" <= 6"); }
答案:输出是 “>6”。
解读:当运算表达式中存在有符号数和无符号数时,有符号数隐式转换成了无符号数(即底层的补码不变,但是此数从有符号数变成了无符号数)。注意,正数的补码为其本身,负数的补码为其反码+1。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果 ”>6”。
问题4:代码输出2
#include<stdio.h> #define N 500 void main() { unsigned char count; for(count = 0; count < N; count++) { printf("---%d---\n", count); } }
答案:进入不断打印count值的死循环。
解读:因为unsigned char 类型变量的最大值为255,所以count只能从0一直增加到255,然后又恢复为0,无法退出for循环。
问题5:代码输出3
int foo(void) { int i; char c = 0x80; i = c; if(i > 0) return 1; return 2; }
答案:返回值为2。
解读:在C语言中,char 类型是有符号的,所以
0x80 被解释为一个负数,二进制表示为 10000000,最高位是符号位。表示的负数值可以通过以下步骤计算:
首先,将除了最高位之外的其他位取反,得到01111111。然后,将取反后的结果加1,得到10000000,所以为-128。
问题6:给定的位域结构体,它在内存中占用多少字节(32位编译器)?
struct A { char t : 4; // 4位 char k : 4; // 4位 unsigned short i : 8; // 8位 unsigned long m; // 4字节 };
根据结构体内存对齐原则,共占用8字节。
问题7:在32位系统中,有如下结构体,那么sizeof(fun)的数值是?
#pragma pack(1) struct fun { int i; // 4字节 double d; // 8字节 char c; // 1字节 };
答案:sizeof(fun)得到的结果是13。
解读:因为预处理语句 ”#prama pack(1)” 将编译器的字节对齐数改为1了,根据结构体内存对齐原则,该结构体占用的字节数为13。
问题8:代码输出4
#include<stdio.h> void main() { int a[5] = {1, 2, 3, 4, 5}; int *ptr = (int *)(&a + 1); printf("%d, %d", *(a + 1), *(ptr - 1)); }
答案:输出为2, 5。
解读: a是数组首元素地址,所以*(a + 1)就是第二个元素a[1]。&a是数组地址,所以&a + 1是整个数组结尾的下一个地址,*(ptr - 1)就是a[4]。
问题9:代码输出5
#include<stdio.h> void main() { char *str[] = {"ab", "cd", "ef", "gh", "ij", "kl"}; //指针数组 char *t; t = (str + 4)[-1]; printf("%s", t); }
答案:输出"gh"。
解读:str表示数组首元素地址,str + 4表示数组第五个元素地址,(str + 4)[-1]表示在第五个元素地址的基础上往前移一个元素并解引用,因此输出是第四个元素。
问题10:代码输出6
unsigned int a = 1; int b = 0; int c = 0; c = a + b > 0 ? 1 : 2;
答案:c的值是1。
解读:有符号数与无符号数一起运算时,有符号数转为无符号数。有符号数int b = 0的在内存中的补码是0,因此转为无符号数之后依然是0,a + b == 1 > 0,c == 1。
10.3 检查错误
问题11:检查错误1
#include<stdio.h> void main() { char *s = "AAA"; s[0] = 'B'; printf("%s", s); }
AAA"是字符串常量,s是指针,指向这个字符串常量,所以声明s的时候就有问题,应该是const char* s="AAA"。
字符串字面量(如 "AAA")是存储在只读内存区域,尝试修改这些字面量的字符(如 s[0] = 'B';)会导致未定义行为,通常是程序崩溃。
问题12:判断下列表达式正确与否?
char str[2][3] = {“a”, “b”}; // 正确,str是一个可存放两个字符串的字符串数组 char str[2][3] = {{1, 2}, {3, 4}, {5, 6}}; // 错误,行列不匹配 char str[] = {“a”, “b”}; // 错误,字符数组不能存放两个字符串 char str[2] = {“a”, “b”}; // 错误,字符数组不能存放两个字符串
答案:以注释形式展示。
注意:在C语言中字符用’’括起来,而字符串用””括起来。
嵌入式软件面试宝典包含简历制作、笔试准备、面试八股文、企业真题等。